Rename-Item : add unique numeric sequence to prevent duplicate file names - powershell

I need a way to rename files in a directory that would result in an error with a simple Rename-Item. The files need the same 10 digit code followed by 4 digit place holder (numbers only please).
Current file names:
01_img_0028.JPG
01_img_0029.JPG
02_img_0028.JPG
02_img_0029.JPG
Considering the files above, renaming the files with a split (using the 4 digit in the original name) would fail because there will be files with the same name:
B0000000000.0028.JPG
B0000000000.0029.JPG
B0000000000.0028.JPG
B0000000000.0029.JPG
Does anyone have an idea to get around this? The 4 digits can be any sequence of numbers but it would be great if we could make the end result look like:
B0000000000.0001.JPG
B0000000000.0002.JPG
B0000000000.0003.JPG
B0000000000.0004.JPG
Here is my current code that will rename all unique files and the first of duplicates, but error out on files that would then be duplicate names:
$jpgToRename = GCI -Path $pathToRename -Filter '*.jpg' -R
foreach ($jpg in $jpgToRename) {
$splitPath = $jpg.FullName.Split("\\")
$newName = -join ($splitPath[7], ".", $jpg.BaseName, ".PC_850.jpg")
Rename-Item $jpg.FullName -NewName $newName
}

Using a counter here would keep this simple for your need:
$jpgToRename = GCI -Path $pathToRename -Filter '*.jpg' -R
$counter = 1
foreach($jpg in $jpgToRename){
$splitPath = $jpg.FullName.Split("\\")
$formattedCounter = $counter.ToString("0000")
$newName = -Join($splitPath[7], ".",$formattedCounter, $jpg.BaseName, ".PC_850.jpg")
Rename-Item $jpg.FullName -NewName $newName
$counter++
}

Related

Batch renaming files by PowerShell?

How can I rename files in a folder that have random names and random extensions to a sequence like the example below: 0001.pdf 0002.pdf ..... 0100.png and continue.
And if possible then generate a .txt file with the names and extensions generated.
For the .txt file if not possible Powershel could be another application.
Searching I got the code below, but I can't fix it for the task I need.
Dir | Rename-Item –NewName { $_.name –replace " - ","0" }
Wrap the call to Rename-Item in ForEach-Object then maintain a counter in a variable:
$fileNumber = 1
Get-ChildItem path\to\folder\containing\random\files -File |ForEach-Object {
# Construct new file name
$newName = '{0:0000}{1}' -f $fileNumber,$_.Extension
# Perform rename
$_ |Rename-Item -NewName $newName
# Increment number
$fileNumber++
}

Bulk renaming files with different extensions in order using powershell

is there a way to bulk rename items such that a folder with the items arranged in order would have their name changed into numbers with zero padding regardless of extension?
for example, a folder with files named:
file1.jpg
file2.jpg
file3.jpg
file4.png
file5.png
file6.png
file7.png
file8.jpg
file9.jpg
file10.mp4
would end up like this:
01.jpg
02.jpg
03.jpg
04.png
05.png
06.png
07.png
08.jpg
09.jpg
10.mp4
i had a script i found somewhere that can rename files in alphabetical order. however, it seems to only accepts conventionally bulk renamed files (done by selecting all the files, and renaming them such that they read "file (1).jpg" etc), which messes up the ordering when dealing with differing file extensions. it also doesn't seem to rename files with variations in their file names. here is what the code looked like:
Get-ChildItem -Path C:\Directory -Filter file* | % {
$matched = $_.BaseName -match "\((?<number>\d+)\)"
if (-not $matched) {break;}
[int]$number = $Matches["number"]
Rename-Item -Path $_.FullName -NewName "$($number.ToString("000"))$($_.Extension)"
}
If your intent is to rename the files based on the ending digits of their BaseName you can use Get-ChildItem in combination with Where-Object for filtering them and then pipe this result to Rename-Item using a delay-bind script block.
Needles to say, this code does not handle file collision. If there is more than one file with the same ending digits and the same extension this will error out.
Get-ChildItem -Filter file* | Where-Object { $_.BaseName -match '\d+$' } |
Rename-Item -NewName {
$basename = '{0:00}' -f [int][regex]::Match($_.BaseName, '\d+$').Value
$basename + $_.Extension
}
To test the code you can use the following:
#'
file1.jpg
file2.jpg
file3.jpg
file4.png
file5.png
file6.png
file7.png
file8.jpg
file9.jpg
file10.mp4
'# -split '\r?\n' -as [System.IO.FileInfo[]] | ForEach-Object {
$basename = '{0:00}' -f [int][regex]::Match($_.BaseName, '\d+$').Value
$basename + $_.Extension
}
You could just use the number of files found in the folder to create the appropriate 'numbering' format for renaming them.
$files = (Get-ChildItem -Path 'D:\Test' -File) | Sort-Object Name
# depending on the number of files, create a formating template
# to get the number of leading zeros correct.
# example: 645 files would create this format: '{0:000}{1}'
$format = '{0:' + '0' * ($files.Count).ToString().Length + '}{1}'
# a counter for the index number
$index = 1
# now loop over the files and rename them
foreach ($file in $files) {
$file | Rename-Item -NewName ($format -f $index++, $file.Extension) -WhatIf
}
The -WhatIf switch is a safety measure. With this, no file gets actually renamed, you will only see in the console what WOULD happen. Once you are content with that, remove the -WhatIf switch from the code and run again to rename all your files in the folder

Rename a sequence of files to a new sequence, keeping the suffix

I need help to create a command in PowerShell to rename a sequence of files with this format:
001.jpg
001_1.jpg
002.jpg
002_1.jpg
003.jpg
003_1.jpg
into a new sequence that can start with a number such as 9612449, but keeping intact the suffixes, so new sequence would be:
9612449.jpg
9612449_1.jpg
9612450.jpg
9612450_1.jpg
9612451.jpg
9612451_1.jpg
Assuming that 9612449 is an offset to be added to the existing numbers that make up the first _-separated token or all of the base file names:
# Simulate a set of input files.
$files = [System.IO.FileInfo[]] (
'001.jpg',
'001_1.jpg',
'002.jpg',
'002_1.jpg',
'003.jpg',
'003_1.jpg'
)
# The number to offset the existing numbers by.
$offset = 9612449 - 1
# Process each file and apply the offset.
$files | ForEach-Object {
# Split the base name into the number and the suffix.
$num, $suffix = $_.BaseName -split '(?=_)', 2
# Construct and output the new name, with the offset applied.
'{0}{1}{2}' -f ($offset + $num), $suffix, $_.Extension
}
The above yields the output shown in your question.
Applied to a real file-renaming operation, you'd do something like:
Get-ChildItem -LiteralPath . -Filter *.jpg |
Rename-Item -NewName {
$num, $suffix = $_.BaseName -split '(?=_)', 2
'{0}{1}{2}' -f ($offset + $num), $suffix, $_.Extension
} -WhatIf
Note: The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf once you're sure the operation will do what you want.

How do I most efficiently move, rename files and log this action?

I have the following CSV list (in reality 1000s of lines):
needle,code
123456,AB
121212,BB
33333333,CVV
And I have a directory (C:\old_files) containing PDF files (again, 1000s in reality):
dsadsadsa.343222.dsads23213jkjl.saddsa.pdf
dsadsadsa.123456.dsads23213jkjl.saddsa.pdf
dsadsadsa.111111.dsads23213jkjl.saddsa.pdf
dsadsadsa.33333333.dsads23213jkjl.saddsa.pdf
dsadsadsa.33333333.fsdgdsfdsfdsf.dsad.pdf
For each needle in the CSV:
I have to see if there is a PDF containing that needle (there might be 0 or more matches)
If there is a match, I have to
make a copy of the file into a separate folder (D:\new_files)
rename the copied file by prepending the respective code to the name
write an entry into the log.
For the example, I have a match for 123456 and 2 for 33333333, so I have to move a copy of these files into D:\new_files and rename them into:
AB.dsadsadsa.123456.dsads23213jkjl.saddsa.pdf
CVV.dsadsadsa.33333333.dsads23213jkjl.saddsa.pdf
CVV.dsadsadsa.33333333.fsdgdsfdsfdsf.dsad.pdf
The logfile would look like (format needle,code,oldfilepath,newfilepath):
123456,AB,C:\old_files\dsadsadsa.123456.dsads23213jkjl.saddsa.pdf,D:\new_files\AB.dsadsadsa.123456.dsads23213jkjl.saddsa.pdf
33333333,CVV,C:\old_files\dsadsadsa.33333333.dsads23213jkjl.saddsa.pdf,D:\new_files\CVV.dsadsadsa.33333333.dsads23213jkjl.saddsa.pdf
33333333,CVV,C:\old_files\dsadsadsa.33333333.fsdgdsfdsfdsf.dsad.pdf,D:\new_files\CVV.dsadsadsa.33333333.fsdgdsfdsfdsf.dsad.pdf
It is important that I only loop over the files in the directory once, because iterating through all files in a ForEach loop for each needle takes way too long. So with thanks to this forum I'm building a hashtable first:
$pairs = #{}
Import-CSV .\data.csv | ForEach-Object { $pairs[$_.needle] = $_.code+"." }
Get-ChildItem "C:\old_files" | Rename-Item -NewName { "D:\new_files\" + $pairs[$_.Name.Split('.')[1]] + $_.Name }
My first problem here: I am unable to move the file into the new folder.
Q1 How do I properly copy a file from C:\old_files into D:\new_files and rename it?
My second problem: I don't understand how I can add code to the above code.
Q2 How can I create the logfile for each match (and therefore: copied and renamed file)?
You need to actually check if you have a match before copying the matching file.
Get-ChildItem "C:\old_files" | ForEach-Object {
$n = ($_.Name -split '.')[1]
if ($pair[$n]) {
$oldname = $_.FullName
$newname = Join-Path 'C:\new_files' ($pair[$n] + $_.Name)
Copy-Item $oldname $newname
}
}
Do the logging after the copy operation:
Copy-Item $oldname $newname
if ($?) {
# log success information here
} else {
# log error information here
}

Powershell renaming a specific Character

I've been batch renaming .las files in powershell with a simple script:
cd "C:\Users\User\desktop\Folder"
Dir | Rename-Item -NewName {$_.name-replace "-", "" }
Dir | Rename-Item -NewName {$_.name-replace "_", "" }
Dir | Rename-Item -NewName {$_.BaseName+ "0.las"}
This has been working great, but I need to modify it to account for a different naming convention.
The files start out in this format: 123_45-67-890-12W_0
and get converted to 123456789012W00.las
Occasionally the number after the W will be non zero, and I need to carry that on as the last digit, eg. 123_45-67-890-12W_2 needs to go to 123456789012W02
I'm not sure how to use if statements and to select a specific digit in powershell format, which is how I would approach this problem. Does anyone have some ideas on how to go about this?
Thanks
You can use a regular expression to achieve this:
Get-ChildItem "C:\Users\User\desktop\Folder" | ForEach-Object {
#capture everything we need with regex
$newName = $_.Name -replace "(\d{3})_(\d{2})-(\d{2})-(\d{3})-(\d{2})(\w)_(\d)",'$1$2$3$4$5$6$7'
#insert 0 before last digit and append file extension
$newName = $newName.Insert(($newName.Length - 1), "0") + ".las"
#rename file
Rename-Item $_.FullName -NewName $newName
}
You can use the substring method to get all but the last character in the basename, then concatenate the zero, then use substring again to get the basename's last character, then finish off with the .las extension:
Dir | Rename-Item -NewName {($_.BaseName).substring(0,$_.BaseName.length - 1) + "0" + ($_.BaseName).substring($_.BaseName.length -1,1) + ".las"}
# ^^^^This gets everything but the last charcter^^^ ^^^^^^^^^^This gets the last character^^^^^^^^^^