简体   繁体   中英

How do I recursively rename folders with Powershell?

Recursive renaming files using PS is trivial (variation on example from Mike Ormond's blog ):

dir *_t*.gif -recurse 
    | foreach { move-item -literal $_ $_.Name.Replace("_thumb[1]", "")}

I'm trying to recursively rename a folder structure.

The use case is I'd like to be able to rename a whole VS.NET Solution (eg from Foo.Bar to Bar.Foo). To do this there are several steps:

  1. Rename folders (eg \Foo.Bar\Foo.Bar.Model => \Bar.Foo\Bar.Foo.Model)
  2. Rename files (eg Foo.Bar.Model.csproj => Bar.Foo.Model.csproj)
  3. Find and Replace within files to correct for namespace changes (eg 'namespace Foo.Bar' => 'namespace Bar.Foo')

I'm currently working the first step in this process.

I found this posting, which talks about the challenges, and claims a solution but doesn't talk about what that solution is.

I keep running into the recursion wall. If I let PS deal with the recursion using a flag, the parent folder gets renamed before the children, and the script throws an error. If I try to implement the recursion myself, my head get's all achy and things go horribly wrong - for the life of me I cannot get things to start their renames at the tail of the recursion tree.

Here's the solution rbellamy ended up with:

Get-ChildItem $Path -Recurse | %{$_.FullName} |
Sort-Object -Property Length -Descending |
% {
    Write-Host $_
    $Item = Get-Item $_
    $PathRoot = $Item.FullName | Split-Path
    $OldName = $Item.FullName | Split-Path -Leaf
    $NewName = $OldName -replace $OldText, $NewText
    $NewPath = $PathRoot | Join-Path -ChildPath $NewName
    if (!$Item.PSIsContainer -and $Extension -contains $Item.Extension) {
        (Get-Content $Item) | % {
            #Write-Host $_
            $_ -replace $OldText, $NewText
        } | Set-Content $Item
    }
    if ($OldName.Contains($OldText)) {
        Rename-Item -Path $Item.FullName -NewName $NewPath
    }
}

How about this - do a recursive list of the full names, sort it in descending order by the length of the full name, and then run that back through your rename routine.

eg

gci <directory> -recurse |
 foreach {$_.fullname} |
  sort -length -desc

Maybe something in this is useful, here's a snippet that recurses and prepends "pre" to a directory structure

$dirs = Get-ChildItem c:/foldertorecurse -rec |  Where-Object {$_.PSIsContainer -eq 1} |  sort fullname -descending
foreach ( $dir in $dirs ) { rename-item -path $dir.fullname -newname ("pre" + $dir.name) } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM