如何使用PowerShell递归替换文件和文件和文件夹名称中的字符串?

时间:2011-04-13 13:33:05

标签: windows-7 powershell

使用PowerShell(虽然欢迎其他建议),如何以递归方式循环目录/文件夹和

  1. 在所有文件中替换文字A和B,
  2. 重命名所有文件,以便A替换为B,最后
  3. 还重命名所有文件夹,以便A替换为B?

5 个答案:

答案 0 :(得分:12)

通过一些需求改进,我最终得到了这个脚本:

$match = "MyAssembly" 
$replacement = Read-Host "Please enter a solution name"

$files = Get-ChildItem $(get-location) -filter *MyAssembly* -Recurse

$files |
    Sort-Object -Descending -Property { $_.FullName } |
    Rename-Item -newname { $_.name -replace $match, $replacement } -force



$files = Get-ChildItem $(get-location) -include *.cs, *.csproj, *.sln -Recurse 

foreach($file in $files) 
{ 
    ((Get-Content $file.fullname) -creplace $match, $replacement) | set-content $file.fullname 
}

read-host -prompt "Done! Press any key to close."

答案 1 :(得分:3)

我会选择这样的东西:

Get-ChildItem $directory -Recurse |
    Sort-Object -Descending -Property { $_.FullName } |
    ForEach-Object {
        if (!$_.PsIsContainer) {
            ($_|Get-Content) -replace 'A', 'B' | Set-Content $_.FullName
        }
        $_
    } |
    Rename-Item { $_.name -replace 'A', 'B' }

Sort-Object用于确保列出第一个子项(子目录,文件),然后列出后面的目录。 (12345)

答案 2 :(得分:0)

未经测试,但应该给你一个起点:

$a = 'A';
$b = 'B';
$all = ls -recurse;
$files = = $all | where{ !$_.PSIsContainer );
$files | %{ 
   $c = ( $_ | get-itemcontent -replace $a,$b ); 
   $c | out-file $_;
}
$all | rename-item -newname ( $_.Name -replace $a,$b );

答案 3 :(得分:0)

未经测试,可能是我更幸运; - )

$hello = 'hello'
$world = 'world'

$files = ls -recurse | ? {-not $_.PSIsContainer} 

foearch ($file in $files) {
  gc -path $file | % {$_ -replace $hello, $world} | Set-Content $file
  ri -newname ($file.name -replace $hello, $world)
}

ls -recurse | ? {$_.PSIsContainer} | ri -newname ($_.name -replace $hello, $world)

使用相同的递归:

$hello = 'hello'
$world = 'world'

$everything = ls -recurse 

foearch ($thing in $everything) {
  if ($thing.PSIsContainer -ne $true) {
     gc -path $thing | % {$_ -replace $hello, $world} | Set-Content $thing
  }
  ri -newname ($thing.name -replace $hello, $world)
}

答案 4 :(得分:0)

我自己需要这个以及稍微好一点的脚本版本。

我添加了以下内容:

  1. 支持详细参数,以便您可以实际查看脚本所做的更改。
  2. 能够指定文件夹,以便限制更改。
  3. 添加bower.json,txt和md以包含扩展名。
  4. 首先搜索并替换内容,稍后重命名。
  5. 如果未找到搜索字符串,请勿替换内容(这样可以避免在修改日期中进行不必要的更改)。
  6. [CmdletBinding(SupportsShouldProcess=$true)]
    Param()
    
    $match = "MyProject" 
    $replacement = Read-Host "Please enter project name"
    
    $searchFolders = @("MyProject.JS", "MyProject.WebApi", ".")
    $extensions = @("*.cs", "*.csproj", "*.sln", "bower.json", "*.txt", "*.md")
    foreach($searchFolderRelative in $searchFolders)
    {
        $searchFolder = join-path (get-location) $searchFolderRelative
        Write-Verbose "Folder: $searchFolder"
    
        $recurse = $searchFolderRelative -ne "."
    
        if (test-path $searchFolder)
        {
            $files = Get-ChildItem (join-path $searchFolder "*") -file -include $extensions  -Recurse:$recurse |
                        Where-Object {Select-String -Path $_.FullName $match -SimpleMatch -Quiet}
    
            foreach($file in $files) 
            { 
                Write-Verbose "Replaced $match in $file"
                ((Get-Content $file.fullname) -creplace $match, $replacement) | set-content $file.fullname 
            }
    
            $files = Get-ChildItem $searchFolder -filter *$match* -Recurse:$recurse
    
            $files |
                Sort-Object -Descending -Property { $_.FullName } |
                % {
                    Write-Verbose "Renamed $_"
                    $newName = $_.name -replace $match, $replacement
                    Rename-Item $_.FullName -newname $newName -force
                }       
        }
        else
        {
            Write-Warning "Path not found: $searchFolder"
        }
    }
    

    请注意,答案中的一个更改是上面只在指定的文件夹中而不是在root中的recurses文件夹。如果您不想这样,那么只需设置$recurse = true