Search code examples
powershellswapbatch-rename

How to swap parts of multiple filenames?


I basically have a ton of documents where the filenames contain the height and width of the content. The creator of the files put the height infront of the width but i'd like to see them swapped. The Problem is the naming scheme is not always the same. Here are some examples:

(2- or 3-digit number is height, number+sp is width)

123_5sp_abc
99_5sp
abc 123_3sp
abc 123_7sp_def
abc 99_1sp
abc 99_2sp_def
abc_123_4sp
abc_123_6sp_def
abc_99_2sp
abc_99_3sp_def
abc def ghj 99_4sp
abc_def_ghj 99_5sp

Meaning the only thing that is always the same is height and width connected by _ .

I came up with different solutions for different combinations. Something like this:

Get-ChildItem -Path C:\Temp\test|
where -filterscript {$_.BaseName -match '(.*)_(\d{2,3})_(\d.*)_(.*)'}|
Rename-Item -NewName {$matches[1]+'_'+
                      $matches[3]+'_'+
                      $matches[2]+'_'+
                      $matches[4]+$_.Extension}

Nothing I tried could handle every variation

My question: Is there an easy way to include all variations?

Thanks for your effort!


Solution

  • $regex = '([0-9]{2,3})_([0-9]+sp)'
    
    Get-ChildItem -LiteralPath 'C:\Temp\test' |
        Where-Object -FilterScript { $_.BaseName -match $regex } |
        Rename-Item -NewName {
            $_.Name -replace $regex, '$2_$1'
        }
    

    If the sp is part of the name, it should be in the regex to help it match the right thing. And you can replace the match groups, without having to rebuild the whole name around it. I think this covers all your examples.