使用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”区分大小写。