【问题标题】:Replace a string in directory names, filenames and file content using Powershell使用 Powershell 替换目录名、文件名和文件内容中的字符串
【发布时间】:2017-08-12 19:19:12
【问题描述】:

我在特定目录和子目录中有数千个文件。

  • C:\Food\
  • C:\Food\Avocado.sln(也包含字符串“Avocado”)
  • C:\Food\Avocado.DataModel\
  • C:\Food\Avocado.DataModel\AvocadoModel.cs(也包含字符串“Avocado”)

我想在目录名、文件名和文件内容中将字符串“Avocado”的所有实例替换为“Burger”,例如

  • C:\Food\
  • C:\Food\Burger.sln(“文件内容中的鳄梨”的所有实例现在都更改为“汉堡”)
  • C:\Food\Burger.DataModel\
  • C:\Food\Burger.DataModel\BurgerModel.cs(“文件内容中的鳄梨”的所有实例现在都更改为“汉堡”)

我想使用 Powershell 来完成这项工作。

我该怎么做?

【问题讨论】:

  • 要检查哪些文件类型,仅.sln.cs?只检查包含鳄梨或一般文件夹中的文件?仅在文件名或所有文件名中检查内容鳄梨的文件?
  • @LotPings 所有文件。我现在正在学习如何使用powershell,所以在下面发布了我的答案。我相信还有其他(更好的)方法可以实现我想要的。我也意识到,当我的目录包含二进制文件时,我的解决方案可能存在问题(所以对于我的情况,我删除了 \bin\obj 目录)

标签: powershell


【解决方案1】:

我使用下面的脚本来更改目录名、文件名和文件内容。我知道使用管道 | 运算符可能有更简单的方法来做到这一点,但这对我来说很有意义(我对 Powershell 比较陌生)。

# change these three variables to suit your requirements
$baseDirectory = "C:\Food\"
$a = "Avocado"
$b = "Burger"

# get all files
$files = Get-ChildItem $baseDirectory -File -Recurse
# get all the directories
$directorys = Get-ChildItem $baseDirectory -Directory -Recurse

# replace the contents of the files only if there is a match
foreach ($file in $files)
{
    $fileContent = Get-Content -Path $file.FullName

    if ($fileContent -match $a)
    {
        $newFileContent = $fileContent -replace $a, $b
        Set-Content -Path $file.FullName -Value $newFileContent
    }
}

# change the names of the files first then change the names of the directories

# iterate through the files and change their names
foreach ($file in $files)
{
    if ($file -match $a)
    {
        $newName = $file.Name -replace $a, $b
        Rename-Item -Path $file.FullName -NewName $newName
    }
}

# reverse the array of directories so we go deepest first
# this stops us renaming a parent directory then trying to rename a sub directory which will no longer exist
# e.g.
# we might have a directory structure "C:\Rename\Rename"
# the file array would be [ C:\Rename, C:\Rename\Rename ]
# without reversing we'd rename the first directory to "C:\NewName"
# the directory structure would now be "C:\NewName\Rename"
# we'd then try to rename C:\Rename\Rename which would fail
[array]::Reverse($directorys)

# iterate through the directories and change their names
foreach ($directory in $directorys)
{
    if ($directory -match $a)
    {
        $newName = $directory.Name -replace $a, $b
        Rename-Item -Path $directory.FullName -NewName $newName
    }
}

【讨论】:

    【解决方案2】:

    我什至不会尝试编辑潜在的二进制文件,
    所以以下脚本只处理指定的文件类型
    并且为了安全做备份。

    $baseDirectory = "C:\Food\"
    $a = "Avocado"
    $b = "Burger"
    $Include = '*.sln','*.cs'
    
    
    Pushd $baseDirectory
    
    # process all file and  directory names 
    Get-ChildItem -Filter "*$a*" -Recurse|
      Rename-Item -NewName {$_.Name -replace $a,$b} -confirm
    
    
    Get-ChildItem -Include $Include -Recurse | ForEach-Object{
      if (Select-String -Path $_ -Pattern $a -quiet){
        $BakName = "{0}.bak" -f $_.FullName
        $OldName = $_.FullName
        $_ | Move-Item -Destination $BakName -force
        (Get-Content $BakName) -replace $a,$b | Set-Content $OldName
      }
    }
    PopD
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-06
      • 1970-01-01
      • 2017-01-31
      • 1970-01-01
      相关资源
      最近更新 更多