Search code examples
powershellget-childitem

Powershell - Rename files recursively adding upper folder as prefix to NewName


I have this kind of tree folders structure:

c:\Loc_2636\08\20220801.csv
c:\Loc_2636\06\20220607.csv
c:\Loc_2538\07\20220701.csv

i would like to add to any files suffix of upper "Loc_*" folder. At the end they should be like:

c:\Loc_2636\08\Loc_2636_20220801.csv
c:\Loc_2538\07\Loc_2538_20220701.csv

I thought it was simple but i got in trouble because if I do this:

Get-ChildItem -File -Recurse  | % { Rename-Item -Path $_.PSPath -NewName $_.FullName.Split("\")[5]+"_"+$_.Name -WhatIf} 

This error is raised: A positional parameter cannot be found that accepts argument '+_+20220701.csv.Name'.

Instead if I try to do that through a function

function rena(){
    param ([string]$name, [string]$fullpath)
    $arr=$fullpath.Split("\")
    foreach($tmp in $arr)
        {
            if($tmp.ToString().Contains("Loc_")){
                $found=$tmp;
                }
        }
    return $found+"_"+$name
}
Get-ChildItem -File -Recurse  | % { Rename-Item -Path $_.PSPath -NewName {rena($_.Name,$_.FullName) -WhatIf}} 

another error is raised

Cannot evaluate parameter 'NewName' because its argument is specified as a script block and there is no input. A script block cannot be evaluated without input.

I'm quite confused since i already used function inside Get-ChildItem command but I never got this error.

Thank you in advance for any help.


Solution

  • You can do this like below:

    Get-ChildItem -File -Recurse | Where-Object { $_.DirectoryName -match '\\(Loc_\d+)' } | 
    Rename-Item -NewName { '{0}_{1}' -f $matches[1], $_.Name } -WhatIf
    

    Remove the -WhatIf switch if what is displayed in the console is OK. Then run again to actually start renaming the files.

    To prevent renaming files that have already been renamed (when running more than once), extend the Where-Object clause to Where-Object { $_.DirectoryName -match '\\(Loc_\d+)' -and $_.Name -notlike 'Loc_*' }