As the title suggests I am trying to create a Powershell script to rename multiple files. The script refers to a csv file which contains a string in a csv file "column A". If the result is true then I would like to rename the file from "Column B".
Ive managed to get my code to work based on a string but this is the next stage - can anyone help me please?
Current Code:
Get-ChildItem -Path C:\ -Recurse -ErrorAction SilentlyContinue |
Where {($_.Name -like "*blah*")} |
Rename-Item -NewName {[System.IO.Path]::GetFileNameWithoutExtension($_.fullname) ".BackupFile"}
Thanks as always!
CodePudding user response:
The following assumes that your CSV file contains the file names with extension - adjust as needed.
Build a hashtable from the CSV whose entries are keyed by
Column A
values and each contain the correspondingColumn B
value.Filter the
Get-ChildItem
output withWhere-Object
to only process files whose name is present as a key in the hashtable.- Note that switch
-File
is added to theGet-ChildItem
call below, so as to process files only (not also directory objects).
- Note that switch
Rename each matching file to the value of the relevant hashtable entry.
# Build a hashtable from the CSV that with old-name-new-name pairs.
$ht = [ordered] @{} # Note: you can omit [ordered] in this case.
Import-Csv file.csv |
ForEach-Object { $ht[$_.'Column A'] = $_.'Column B' }
Get-ChildItem -Path C:\ -File -Recurse -ErrorAction SilentlyContinue |
Where-Object { $ht.Contains($_.Name) } |
Rename-Item -NewName { $ht[$_.Name] } -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.
Note: As an alternative to filtering Get-ChildItem
output with Where-Object
after the fact, you could use the former's -Include
parameter as follows:
-Include $ht.Keys
- However, up to at least PowerShell 7.2.x,
-Include
is actually slower than a post-filtering solution - see this answer.