As commented, it would be a lot simpler if you put the old and new ID values in a CSV file like this:
"OldID","NewID"
"12345","98765"
"23456","87654"
"34567","76543"
Then, something like below should work:
# read this CSV to get an array of PSObjects
$ids = Import-CSV -Path 'D:\ReplaceId.csv'
# build a lookup table from the $ids variable
$hash = @{}
$ids | ForEach-Object { $hash[$_.OldID] = $_.NewID }
# next, get a list of all files that have names starting with any
# of the 5 digits from column 'OldID' and loop through
Get-ChildItem -Path 'THE PATH TO YOUR DIRECTORY' -Filter '*.pdf' -File |
Where-Object { $hash.Keys -contains $_.Name.Substring(0,5) } |
ForEach-Object {
# get the value for the new ID from the lookup hashtable
# and combine it with the remainder of the filename
$newName="{0}{1}" -f $hash[$($_.Name.Substring(0,5))], $_.Name.Substring(5)
$_ | Rename-Item -NewName $newName -WhatIf
}
If the console info shows the correct replacement names, remove the -WhatIf
switch to actually start renaming the files
If you add the -Recurse
switch to the Get-ChildItem
cmdlet, the code will also rename files inside any subfolder.
Update
Of course, the above assumes there is no mix of Old and New Id numbers in the folder. Since you commented that this is the case you will get file already exists errors.
To overcome that, you need to make sure the new filenames are unique inside the folder. You can do that for instance like this.
It appends an index number between brackets to the name if a file with that name already exists.
Get-ChildItem -Path 'D:\Test' -Filter '*.pdf' -File |
Where-Object { $hash.Keys -contains $_.Name.Substring(0,5) } |
ForEach-Object {
# get the value for the new ID from the lookup hashtable
# and combine it with the remainder of the filename
$newId = $hash[$($_.Name.Substring(0,5))]
$newName="{0}{1}" -f $newId, $_.Name.Substring(5)
# since a filename with the new ID may already exist,
# you need to create a unique filename by appending an indexnumber
$fullName = Join-Path -Path $_.DirectoryName -ChildPath $newName
$index = 1
while (Test-Path -Path $fullName -PathType Leaf) {
$newName="{0}{1}({2}){3}" -f $newId, $_.BaseName.Substring(5), $index++, $_.Extension
$fullName = Join-Path -Path $_.DirectoryName -ChildPath $newName
}
$_ | Rename-Item -NewName $newName -WhatIf
}
Before:
D:\TEST 12345_id_user.pdf 12345_id_user2.pdf 12345_id_user3.pdf 23456_id_user.pdf 34567_id_user.pdf 34567_id_user2.pdf 76543_id_user2.pdf 98765_id_user.pdf
After:
D:\TEST 76543_id_user.pdf 76543_id_user2(1).pdf 76543_id_user2.pdf 87654_id_user.pdf 98765_id_user(1).pdf 98765_id_user.pdf 98765_id_user2.pdf 98765_id_user3.pdf
Or if you want to increase the index number you already seem to apply, use this:
Get-ChildItem -Path 'D:\Test' -Filter '*.pdf' -File |
Where-Object { $hash.Keys -contains $_.Name.Substring(0,5) } |
ForEach-Object {
# get the value for the new ID from the lookup hashtable
# and combine it with the remainder of the filename
$newId = $hash[$($_.Name.Substring(0,5))]
$newName="{0}{1}" -f $newId, $_.Name.Substring(5)
# since a filename with the new ID may already exist,
# you need to create a unique filename by incrementing the indexnumber
# get the basename of the new name without any index numbers at the end
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($newName) -replace '\d+$'
$extension = $_.Extension
# get an array of all file and folder names of items with a similar name already present in the folder
$similar = @(Get-ChildItem $_.DirectoryName -Filter "$baseName*$extension" | Select-Object -ExpandProperty Name)
$index = 1
while ($similar -contains $newName) {
$newName="{0}{1}{2}" -f $baseName, $index++, $extension
}
$_ | Rename-Item -NewName $newName -WhatIf
}
Before:
D:\TEST 12345_id_user.pdf 12345_id_user2.pdf 12345_id_user3.pdf 23456_id_user.pdf 34567_id_user.pdf 34567_id_user2.pdf 76543_id_user2.pdf 98765_id_user.pdf
After:
D:\TEST 76543_id_user.pdf 76543_id_user1.pdf 76543_id_user2.pdf 87654_id_user.pdf 98765_id_user.pdf 98765_id_user1.pdf 98765_id_user2.pdf 98765_id_user3.pdf
5
solved Script for renaming files in a specific way