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

发布于 2024-10-31 21:06:18 字数 143 浏览 1 评论 0原文

使用 PowerShell(尽管欢迎其他建议),如何递归循环目录/文件夹并

  1. 在所有文件中将文本 A 替换为 B,
  2. 重命名所有文件以便 A 被 B 替换,最后
  3. 重命名所有文件夹以便 A 为换成B?

With PowerShell (although other suggestions are welcome), how does one recursively loop a directory/folder and

  1. replace text A with B in all files,
  2. rename all files so that A is replaced by B, and last
  3. rename all folders also so that A is replaced by B?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

榕城若虚 2024-11-07 21:06:18

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

$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."

With a few requirements refinements, I ended up with this script:

$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."
喜爱皱眉﹌ 2024-11-07 21:06:18

我会采用这样的方法:

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)

I would go with something like this:

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' }

The Sort-Object is there to ensure that first children (subdirs, files) are listed and then directories after them. (12345)

闻呓 2024-11-07 21:06:18

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

$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 );

Untested, but should give you a starting point:

$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 );
零時差 2024-11-07 21:06:18

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

$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)
}

Untested, may be I'm more lucky ;-)

$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)

To use the same recursion:

$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)
}
揽清风入怀 2024-11-07 21:06:18

我自己需要这个,下面是稍微好一点的脚本版本。

我添加了以下内容:

  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 即可。

I needed this for myself and below slightly better version of the script.

I added followings:

  1. Support for verbose parameter so you can actually see what changes script has made.
  2. Ability to specify folders so you can limit changes.
  3. Adding bower.json, txt and md in to include extensions.
  4. Search and replace content first, do rename later.
  5. Do not replace content if search string is not found (this avoids unnecessary change in modified date).
[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"
    }
}

Note that one change from the answer is that above recurses folder only in specified folders, not in root. If you don't want that then just set $recurse = true.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文