Garrett
Garrett

Reputation: 649

Partial file rename in powershell with CSV source

I want to rename parts of the filename of a collection of .jpg files. I have built a .csv table with a column of the old partial name and the new partial names. File naming is part1.part2.part3.jpg, and I would like to replace part 1 only. The .csv looks like this:

enter image description here

Here's my code, which seems to only search for the first original name and first new name in the .csv for each source image, effectively only renaming one of the images.

#import naming conventions
$csvData = Import-Csv ".\Orig_to_new.csv"

#rename source file
$csvData | % {
    $original = $_.Original
    $new = $_.Real

    #get the source images
    $sourceImages = GCI -Recurse -Filter *.jpg ".\Renamed_Archive"
    
    foreach($sourceImage in $sourceImages){

        $sourceImage | Rename-Item -NewName { $_.Name -replace $original, $new}
    }
}

Ideally the script would see each sourceImage's original name, and replace it with the new name based on the .csv doc, example change 'abc' to 'xyz' and '123' to '456' based on the provided .csv table.

Disclaimer: I have asked a similar question before and thought I had a working model but I cant get it to function.

Thanks

Upvotes: 0

Views: 102

Answers (1)

Santiago Squarzon
Santiago Squarzon

Reputation: 59822

You can work with this, the renaming part of the script I assume you already know what to do.

  • First, convert your CSV to a hashtable
  • Then you can loop over all your images, split their name using . as a separator (I use (?=\.) to preserve the dots)
  • We know that the position 0 of the array is what you want to replace, here you can use your hashtable to get the new name of that part and replace the position 0 of the Name array for the new Name we get from your CSV.
  • Ultimately you join the array again into a string.
$csv=@'
Original,New
abc,xyz
123,456
qwe,rty
'@|convertfrom-csv

$nameMap=@{}

$csv.foreach({
    if(-not $nameMap.ContainsKey($_.Original))
    {
        $nameMap.Add($_.Original,$_.New)
    }
})

$sourceImages=gci -Recurse -Filter *.jpg -Path .

foreach($image in $sourceImages)
{
    $name=$image.Name -split '(?=\.)'
    $newPart1=$nameMap[$name[0]]
    $name[0]=$newPart1
    $newName=-join $name

    'Old Name: {0} // New Name: {1}' -f $image.Name,$newName
}

# Looks like this:

PS /~> ./script.ps1
Old Name: 123.part2.part3.jpg // New Name: 456.part2.part3.jpg
Old Name: abc.part2.part3.jpg // New Name: xyz.part2.part3.jpg
Old Name: qwe.part2.part3.jpg // New Name: rty.part2.part3.jpg

Edit: Adding full script code here, as well as new If condition.

#import naming conventions
$csv = Import-Csv ".\table.csv"

$nameMap=@{}

$csv.foreach({
    if(-not $nameMap.ContainsKey($_.Original)){
        $nameMap.Add($_.Original,$_.New)
    }
})

#identify files for renaming
$sourceImages = Get-ChildItem -Recurse -Filter *.jpg -Path ".\images"

foreach($image in $sourceImages)
{
    $name=$image.Name -split '(?=\.)'

    # Adding this If condition, reasoning below.
    # Rename files only If the position 0 of the splitted name is in our nameMap hashtable.
    # This is because if it's not there you would end up with files named like:
    # "..part2.part3.jpg" because $newPart1 var would be null.
    if($nameMap.ContainsKey($name[0]))
    {
        $newPart1=$nameMap[$name[0]]
        $name[0]=$newPart1
        $newName=-join $name

        'Old Name: {0} // New Name: {1}' -f $image.Name,$newName

        Rename-Item $image.FullName -NewName $newName
    }
}

Upvotes: 1

Related Questions