Is it possible to rename each file in a folder with a different name using powershell or a batch file? - powershell

I've tried looking this up but have got nowhere so far and I'm on a time limit.
Let's say I have three files that have similar clones in multiple folders:
(folder1)
image1.png
image2.png
image3.png
(folder2)
image1.png
image2.png
image3.png
I want to rename these using cmd prompt, powershell, or using a .bat to:
(folder1)
B-Sign.png
B-Gauge.png
B-Cup.png
(folder2)
G-Sign.png
G-Gauge.png
G-Cup.png
I intend to run the commands for each folder as only the front of the name is different. I want something simple.
rename-item *.png B-Sign.png
rename-item *.png B-Gauge.png
When it needs a different prefix I would just find and replace the prefix with the new one using ctrl+H in notepad.
Problem is I can't figure out, in any of these, how to automatically cycle to the next file in the folder instead of changing all of the files' names at once. Any one can help?

Yes that's very easy in PowerShell:
Get-ChildItem "C:\temp\Folder1" |
Rename-Item -NewName { "B-" + $_.Name }
The new name is a result of an Expression that Rename-Item knows to evaluate. Because the information is sent down the pipeline the Rename-Item command is run once per file, resulting in names like your example.
Also you can use the filter parameter as you described with either of the below:
Get-ChildItem "C:\temp\Folder1\*.png" |
Rename-Item -NewName { "B-" + $_.Name }
I prefer to filter using the -Filter parameter:
Get-ChildItem "C:\temp\Folder1" -Filter *.png |
Rename-Item -NewName { "B-" + $_.Name }
You can store the folder in a variable too:
$Folder = "C:\temp\Folder1"
Get-ChildItem $Folder -Filter *.png |
Rename-Item -NewName { "B-" + $_.Name }
Update:
Per comments here's an example to correlate a list of prefixes with the renames you want to do:
$Prefix = 'B-'
$NewNames =
#(
'Sign'
'Guage'
'Cup'
)
# If New names are stored ina file simply do:
# $NewNames = Get-Content <FilePath>
$Folder = "C:\temp\Test_10-30-20"
$Files = Get-ChildItem $Folder -Filter *.png
For( $i = 0; $i -lt $Files.Count; ++$i )
{
$CurrentFile = $Files[$i]
$NewName = $Prefix + $NewNames[$i] + $CurrentFile.Extension
Rename-Item $CurrentFile.FullName -NewName $NewName
}

Related

Renaming multiple files with different names

I am a programmer by no means and am brand new to using powershell, but have been tasked with setting up some batch export processes for daily files we FTP. I need to come up with a script that will take changing file names and change them within the same directory to new names;
Example: files will come in as below (YYYYMMDD will be the changing variable)
YYYYMMDD_Share_Support.txt
YYYYMMDD_Person_Support.txt
We need them to be stripped from the above to:
Share.txt
Person.txt
so on and so forth.
I have found ways to make this work, but only on an as needed basis for one file at a time with specific names, not names that will change daily.
So far I am using:
Get-ChildItem -Filter *.txt
Dir | %{Rename-Item $_ -NewName ("NEWFILENAME.txt" -f $nr++)}
You could use the regex -replace operator inside a pipeline-bound scriptblock:
$files = Get-ChildItem -filter *.txt
$files |Rename-Item -NewName { $_.Name -replace '^\d{8}_(.*)_Support\.txt$', '$1.txt' }
As suggested by TheIncorrigible1, if you know the relative position of the word you need, you can also use -split:
$files |Rename-Item -NewName {'{0}.txt' -f ($_.Name -split '_')[-2]} # grab 2nd last word
How about:
dir *.txt |
rename-item -newname { $null,$base,$null = $_.basename -split '_'; "$base.txt" } -whatif
Probably a longer version of the answer. An alternative mentioned by #TheIncorrigible1
$logDir = "D:\Satish\TestFolders"
cd $logDir
$files = ls
foreach ($file in $files){
$fileSplit=($file.ToString()).split("_")
ren $file "$($fileSplit[1]).txt"
}
And for Share.txt to YYYYMMDD_Share_Support.txt
$logDir = "D:\Satish\TestFolders"
cd $logDir
$files = ls
$date = Get-Date -Format "yyyyMMdd"
foreach ($file in $files){
$fileSplit=($file.ToString()).split(".")
ren $file "$($date)_$($fileSplit[0])_Support.txt"
}

Adding leading zeros to file name strings using PowerShell

I'm new to using PowerShell and am wondering how to simply pad number strings contained in several similar file names to have the same number of digits in each file name.
That is, I have a folder containing these 300 files:
dummy name 1.txt through dummy name 300.txt
and would simply like rename the files that have less than 3 digits in them to all have exactly 3 digits, such as:
dummy name 001.txt through dummy name 300.txt
If your files were produced sequentially and you've got name1.txt
, name2.txt, etc.,
And you want name0001.txt, name0002.txt, etc.
You can do
$j=1;
foreach ($i in Get-ChildItem "./name?.txt" -Name) {
echo $i;
$new_name = "name000" + $j + ".txt";
Rename-Item -Path $i -NewName $new_name;
$j=$j+1;
}
... Then do it again, changing $j to 10 at the start, taking a 0 off, and so on for the hundreds.
Okay for a one off and if you can then fix what's producing the files in the first place.
#TessellatingHeckler gave good answer in the comments:
gci | ren -n {[regex]::replace($_.name, '\d+', {"$args".PadLeft(3, '0')})}
I would do it like this:
$i=0;
$nameLike='dummy name'
[int]$currentid=0
#RENAME TO REMOVE THE SPACE IN THE MIDDLE
gci -File -Path "./" | where{ $_.name -like "$nameLike*"} | %{
#remove space in the middle
$newname = $_.Name.Split(' ')[0] + $_.Name.Split(' ')[1]
#convert the name into the padding you want (3)
[int]::TryParse($_.Name.Split(' ')[2].Split('.')[0],[ref]$CurrentId) | Out-Null
$newname = $newname + $CurrentId.ToString("000") + $_.Extension
Rename-Item -Path $_.FullName -NewName $newname
}
Details in here:
https://medium.com/#josegabrielortegac/powershell-renaming-files-with-powershell-e9012573647a?sk=502148e039058d84fe34608d77cd1aa2
Try this:
1..300 | %{
$source = "dummy name $_.txt"
$target = ('dummy name {0:00#}.txt' -f $_)
rename-item $source -NewName $target
}
Notes:
The outer loop is a little unconventional. Most scripters code this to resemble a java for loop.
The choice of single and double quotes is intentional. Be careful.
The code is a little inelegant, because some parts of the filename are typed in twice.
The assumption is that all 300 files exist. If not, you will get errors.
try this:
Get-ChildItem "c:\temp\" -file -Filter "*.txt" | where basename -match ". \d{1,2}$" | %{
$res=$_.BaseName -split '(.)(\d{1,2})$'
$newnamme="{0}\{1} {2:D3}{3}" -f $_.Directory, $res[0], [int]$res[2], $_.Extension
Rename-Item $_.FullName $newnamme
}

Cycle through sub-folders to rename files in Powershell

I have a file directory that contains many folders within it. Inside each of these sub-folders, I have a variety of files. I would like to go through each file, rename some of the items, and add extensions to some of them. I am using Powershell to do this.
I have file names with "." that all need to be replaced with "_" for example, "wrfprs_d02.03" should be "wrfprs_d02_03". I was able to successfully do that in one folder with the following code:
dir | rename-item -NewName {$_.name -replace "wrfprs_d02.","wrfprs_d02_"}
After, I make those replacements, I want to add .grb extensions on to some of the files, which all happen to start with "w", and I was able to do that within one folder with:
Get-ChildItem | Where-Object {$_.Name -match "^[w]"} | ren -new {$_.name + ".grb"}
When I step back from one folder and try to do it iteratively within many folders, my code doesn't work. I am in a directory called "Z:\Windows.Documents\My Documents\Test_data\extracted" which contains all my sub-folders that I want to iterate over. I am using the following code:
$fileDirectory = "Z:\Windows.Documents\My Documents\Test_data\extracted"
foreach($file in Get-ChildItem $fileDirectory)
{
dir | rename-item -NewName {$_.name -replace "wrfprs_d02.","wrfprs_d02_"}
Get-ChildItem | Where-Object {$_.Name -match "^[w]"} | ren -new {$_.name + ".grb"}
}
Any ideas on what my problem is?
because you $_ is replaced into loop when you use pipe. I propose you a new code:
$fileDirectory = "Z:\Windows.Documents\My Documents\Test_data\extracted"
Get-ChildItem $fileDirectory -recurse -file -filter "*.*" |
%{
#replace . by _
$NewName=$_.Name.Replace(".", "_")
#add extension grb if name start by w
if ($NewName -like "w*") {$NewName="$NewName.grb"}
#Add path file
$NewName=Join-Path -Path $_.directory -ChildPath $NewName
#$NewName
#rename
Rename-Item $_.FullName $NewName
}
Not sure what error you were getting, but using rename-item can be finicky. Or at least so in my experience.
I used the follow without issue. My files names were different so I replaced all periods with underscores. If the file starts with "W" then it changed the extension for that file.
$FilePath = Get-ChildItem "Z:\Windows.Documents\My Documents\Test_data\extracted" -Recurse -File
foreach ($file in $FilePath)
{
$newName = $file.Basename.replace(".","_")
$New = $newName + $file.Extension
if($file.Name -match "^[w]")
{
Rename-Item $file.FullName -NewName "$($New).grb"
}
else
{
Rename-Item $file.FullName -NewName $New
}
}
Hope that helps.

How to ignore brackets in file names when splitting and renaming?

I have the following PowerShell script that puts all .jpg files found in its subfolders into a 'Scans' folder and renames these .jpg files to match the name of their respective parent directory (=subfolder). When multiple .jpg files exist the renaming process will automatically add a number to the filename, like File_1,jpg and File_2.jpg.
So before the script is run a folder may look like this:
Parent Directory from which script is executed
|
Subfolder (containing .jpg files and the 'Scans' subfolder)
|
Scans (=folder)
Photo.jpg
Picture.jpg
Shot(1).jpg
Shot(2).jpg
Once the script has run the folder looks like this:
Parent Directory from which script is executed
|
Subfolder (containing the 'Scans' subfolder)
|
Scans (=folder containing supposed to contain all .jpg files)
|
Subfolder_1.jpg
Subfolder_2.jpg
Shot(1) (=file moved but extension stripped)
Shot(2) (=file not moved and extension stripped)
So the .jpg files containing parenthesis 'Shot(1).jpg' and 'Shot(2).jpg' are not properly renamed and moved to the 'Scans' folder. In fact their '.jpg' extension is stripped off.
The script works fine as long as the .jpg files do not contain any parentheses (()), as in
'Shot(1).jpg' and 'Shot(2).jpg' → when multiple .jpg files exist
'Pics(2001).jpg' → when the subfolder name contains parentheses as in 'Pics(2001)', the .jpg is correctly renamed, but then contains parentheses and the script would fail again when run a second time.
I have read about escaping special characters in other threads but have not been able to implement a solution into the script below. Does anybody here have a solution so that the parentheses are not causing any issues when moving and renaming these .jpg files?
$path = Split-Path -parent $MyInvocation.MyCommand.Definition
function renamePhotos {
# Loop through all directories
$dirs = dir $path -Recurse | Where { $_.psIsContainer -eq $true }
foreach ($dir In $dirs) {
$i = 1
$newdir = $dir.parent.name + "_"
$images = Get-ChildItem -Path $dir.fullname -Filter *.jpg -Recurse
foreach ($image In $images) {
$split = $image.name.split(".jpg")
$replace = $split[0] -Replace $split[0],($newdir + $i + ".jpg")
$image_string = $image.fullname.ToString().Trim()
Rename-Item "$image_string" "$replace"
$i++
Move-Item -Path $dir\*.jpg -Destination $dir\Scans
}
}
}
# RUN SCRIPT
renamePhotos
"SCRIPT FINISHED"
The -replace operator does a regular expression replacement. If you want to use it you need to escape special characters in your source string:
-replace [regex]::Escape($split[0]), "$newdir$i.jpg"
However, you don't need that in the first place. Simply use the appropriate properties of the FileInfo objects:
$images = Get-ChildItem -Path $dir.fullname -Filter *.jpg -Recurse
foreach ($image in $images) {
$newname = $newdir + $i + $image.Extension
Rename-Item $image.FullName $newname
$i++
}
Move-Item -Path $dir\*.jpg -Destination $dir\Scans
Or simply move the items to the new location with their new name without renaming them first:
$images = Get-ChildItem -Path $dir.fullname -Filter *.jpg -Recurse
foreach ($image in $images) {
$newname = $newdir + $i + $image.Extension
Move-Item $image.FullName "$dir\Scans\$newname"
$i++
}

Using Powershell how can I bulk rename files recursively and include a counter in the new name?

I have a project where I need to search for multiple pdfs within multiple subfolders which contain a specific string and then rename them using a counter variable. I'm a pretty novice powershell user but I think I've got it pretty close. The only thing that is not working is the counter. The counter variable never changes. This is what I have so far for code:
$prefix = "sample"
$id = 1
Get-ChildItem -Filter "*combined*" -Recurse | Rename-Item -NewName ($prefix + ($id.tostring("000")) + '_regular_' + ($id.tostring("000")) + '.pdf' -f $id++ )
What am I missing? Should I be using a 'foreach' loop?
Yes you need to use a ForEach loop. This will go through and do the renames, ensuring that any files found in subdirectories are preserved in those directories after renaming
Get-ChildItem -Filter "*combined*" -Recurse | %{
$fullId = $id.toString("000")
$curPath = Split-Path $_.FullName
Rename-Item $_.fullname -NewName "$curPath\$($prefix)$($fullId)_regular_$($fullId).pdf" )
$id += 1
}
Here is my edited version of the above code:
$id = 1
Get-ChildItem -Filter "*combined*" -Recurse | %{
$fullId = $id.toString("000")
$curPath = Split-Path $_.FullName
Rename-Item $_.fullname -NewName "$curPath\$($prefix)_$($fullId)_regular_$($fullId).pdf"
$id++
}