使用Powershell替换目录名称,文件名和文件内容中的字符串

问题描述:

我在特定目录和子目录中有数千个文件。使用Powershell替换目录名称,文件名和文件内容中的字符串

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

我想全部更换在目录名称中带有“Burger”的字符串“Avocado”的实例,文件名和文件内容例如

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

我想使用Powershell来做到这一点。

我该怎么做?

+0

什么文件类型检查,只有'.sln'和'.cs'?只检查包含鳄梨或一般文件夹中的文件?只有在文件名或全部文件中才检查内容鳄梨的文件? – LotPings

+0

@LotPings所有文件。我正在学习如何使用PowerShell,因此在下面发布了我的答案。我相信还有其他(更好的)方法可以实现我想要的。我也意识到,当我的目录conatins二进制文件时,我的解决方案可能存在问题(所以对于我的情况,我删除了\ bin和\ obj目录) –

我用下面的脚本来改变目录名,文件名和文件内容。我知道可能有更简单的方法来使用管道运营商|来做到这一点,但这对我来说很有意义(我对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 
    } 
} 

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

$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