Как рекурсивно заменить строку в файлах и именах файлов и папок с помощью PowerShell? - PullRequest
7 голосов
/ 13 апреля 2011

С PowerShell (хотя приветствуются и другие предложения), как можно рекурсивно зацикливать каталог / папку и

  1. заменить текст A на B во всех файлах,
  2. переименуйте все файлы так, чтобы A заменялось на B, а последний
  3. также переименовать все папки, чтобы A заменялось на B?

Ответы [ 5 ]

13 голосов
/ 27 апреля 2011

С некоторыми уточнениями требований я получил следующий скрипт:

$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."
3 голосов
/ 14 апреля 2011

Я бы пошел с чем-то вроде этого:

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)

0 голосов
/ 16 апреля 2014

Мне нужно это для себя, и ниже чуть лучшая версия скрипта.

Я добавил следующее:

  1. Поддержка подробного параметра, чтобы вы могли увидеть, какие изменения внес скрипт.
  2. Возможность указать папки, чтобы вы могли ограничить изменения.
  3. Добавление bower.json, txt и md для включения расширений.
  4. Сначала найдите и замените содержимое, затем переименуйте.
  5. Не заменять содержимое, если строка поиска не найдена (это позволяет избежать ненужного изменения даты изменения).
[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"
    }
}

Обратите внимание, что одно изменение из ответа состоит в том, что вышеупомянутая рекурсивная папка только в указанных папках, а не в корневой Если вы не хотите этого, просто установите $recurse = true.

0 голосов
/ 13 апреля 2011

Не проверено, может быть, мне повезло больше; -)

$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)
}
0 голосов
/ 13 апреля 2011

Не проверено, но должно дать вам отправную точку:

$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 );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...