使用PowerShell脚本查找和replace具有特定扩展名的所有文件

我在Windows Server 2008上有几个configuration文件嵌套像这样:

C:\Projects\Project_1\project1.config C:\Projects\Project_2\project2.config 

在我的configuration我需要做一个stringreplace像这样:

 <add key="Environment" value="Dev"/> 

会变成:

 <add key="Environment" value="Demo"/> 

我想过使用批处理脚本,但没有好的方法来做到这一点,我听说用PowerShell脚本,你可以很容易地执行此操作。 我find了查找/replace的例子,但我希望有一种方法可以遍历C:\ Projects目录下的所有文件夹,并find任何以“.config”扩展名结尾的文件。 当它find一个,我想它来replace我的string值。

有什么好的资源来找出如何做到这一点或任何PowerShell的大师可以提供一些见解?

这是我头顶的第一次尝试。

 $configFiles = Get-ChildItem . *.config -rec foreach ($file in $configFiles) { (Get-Content $file.PSPath) | Foreach-Object { $_ -replace "Dev", "Demo" } | Set-Content $file.PSPath } 

PowerShell是一个不错的select;)枚举给定目录中的文件非常容易,读取它们并进行处理。

脚本可能是这样的:

 Get-ChildItem C:\Projects *.config -recurse | Foreach-Object { $c = ($_ | Get-Content) $c = $c -replace '<add key="Environment" value="Dev"/>','<add key="Environment" value="Demo"/>' [IO.File]::WriteAllText($_.FullName, ($c -join "`r`n")) } 

我将代码拆分为更多行,以供您阅读。 请注意,您可以使用Set-Content而不是[IO.File]::WriteAllText ,但会在最后添加新行。 用WriteAllText你可以避免它。

否则,代码可能如下所示: $c | Set-Content $_.FullName $c | Set-Content $_.FullName

这种方法运作良好:

 gci C:\Projects *.config -recurse | ForEach { (Get-Content $_ | ForEach {$_ -replace "old", "new"}) | Set-Content $_ } 
  • 将“旧”和“新”更改为相应的值(或使用variables)。
  • 不要忘记括号 – 没有它会收到访问错误。

我会去与xml和xpath:

 dir C:\Projects\project_*\project*.config -recurse | foreach-object{ $wc = [xml](Get-Content $_.fullname) $wc.SelectNodes("//add[@key='Environment'][@value='Dev']") | Foreach-Object {$_.value = 'Demo'} $wc.Save($_.fullname) } 

这个PowerShell示例在一个文件夹及其子文件夹中查找string“\ foo \”的所有实例,用“\ bar \”replace“\ foo \”,而不是不包含string“\ foo \”的REWRITE文件。 “这样你不会销毁文件最后更新date时间邮票没有findstring:

 Get-ChildItem -Path C:\YOUR_ROOT_PATH\*.* -recurse | ForEach {If (Get-Content $_.FullName | Select-String -Pattern '\\foo\\') {(Get-Content $_ | ForEach {$_ -replace '\\foo\\', '\bar\'}) | Set-Content $_ } } 

我已经写了一个辅助函数来replace文件中的文本:

 function Replace-TextInFile { Param( [string]$FilePath, [string]$Pattern, [string]$Replacement ) [System.IO.File]::WriteAllText( $FilePath, ([System.IO.File]::ReadAllText($FilePath) -replace $Pattern, $Replacement) ) } 

例:

 Get-ChildItem . *.config -rec | ForEach-Object { Replace-TextInFile -FilePath $_ -Pattern 'old' -Replacement 'new' } 

我发现@Artyom的评论很有​​用,但不幸的是他还没有发布一个答案。

这是我认为最好的版本,被接受的答案的简短版本;

 ls *.config -rec | %{$f=$_; (gc $f.PSPath) | %{$_ -replace "Dev", "Demo"} | sc $f.PSPath} 

在进行recursionreplace时,需要包含path和文件名:

 Get-ChildItem -Recurse | ForEach { (Get-Content $_.PSPath | ForEach {$ -creplace "old", "new"}) | Set-Content $_.PSPath } 

这将在当前目录的文件夹的所有文件中将“old”replace为“new”区分大小写。