用于查找和替换具有特定扩展名的所有文件的PowerShell脚本
我在Windows Server 2008上有几个嵌套的配置文件,如下所示:用于查找和替换具有特定扩展名的所有文件的PowerShell脚本,powershell,scripting,replace,find,Powershell,Scripting,Replace,Find,我在Windows Server 2008上有几个嵌套的配置文件,如下所示: C:\Projects\Project_1\project1.config C:\Projects\Project_2\project2.config <add key="Environment" value="Dev"/> 在我的配置中,我需要执行如下字符串替换: C:\Projects\Project_1\project1.config C:\Projects\Project_2\project
C:\Projects\Project_1\project1.config
C:\Projects\Project_2\project2.config
<add key="Environment" value="Dev"/>
在我的配置中,我需要执行如下字符串替换:
C:\Projects\Project_1\project1.config
C:\Projects\Project_2\project2.config
<add key="Environment" value="Dev"/>
将成为:
<add key="Environment" value="Demo"/>
我曾考虑过使用批处理脚本,但没有很好的方法可以做到这一点,我听说使用PowerShell脚本可以轻松地执行这一点。我已经找到了find/replace的例子,但我希望有一种方法可以遍历我的C:\Projects目录中的所有文件夹,并找到以“.config”扩展名结尾的任何文件。当它找到一个时,我希望它替换我的字符串值
有什么好的资源可以找到如何做到这一点,或者有什么PowerShell大师可以提供一些见解?PowerShell是一个不错的选择;)枚举给定目录中的文件、读取它们并进行处理非常容易 脚本可以如下所示:
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"))
}
Get ChildItem C:\Projects*.config-recurse|
Foreach对象{
$c=($|获取内容)
$c=$c-替换“”,“”
[IO.File]::writealText($\ ux.FullName,($c-join“`r`n”))
}
为了便于阅读,我将代码拆分为更多行。
请注意,您可以使用Set Content代替[IO.File]::writealText
,但它会在末尾添加新行。使用writealText
可以避免它
否则代码可能会如下所示:
$c | Set Content$\ FullName
这是我头上的第一次尝试
$configFiles = Get-ChildItem . *.config -rec
foreach ($file in $configFiles)
{
(Get-Content $file.PSPath) |
Foreach-Object { $_ -replace "Dev", "Demo" } |
Set-Content $file.PSPath
}
我将使用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)
}
这种方法很有效:
gci C:\Projects *.config -recurse | ForEach {
(Get-Content $_ | ForEach {$_ -replace "old", "new"}) | Set-Content $_
}
- 将“旧”和“新”更改为相应的值(或使用变量)
- 不要忘记括号——没有括号,您将收到一个访问错误
Get ChildItem-Path C:\YOUR\u ROOT\u Path\*.-递归
|ForEach{If(获取内容$\全名|选择字符串-模式'\\foo\\\'))
{(获取内容$| ForEach{$|-替换'\\foo\'','\bar\'})}设置内容$|
}
我编写了一个小助手函数来替换文件中的文本:
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'
}
我发现他的评论很有用,但不幸的是他没有给出答案
在我看来,这是公认答案的简短版本,也是最好的版本
ls *.config -rec | %{$f=$_; (gc $f.PSPath) | %{$_ -replace "Dev", "Demo"} | sc $f.PSPath}
进行递归替换时,需要包括路径和文件名:
Get-ChildItem -Recurse | ForEach { (Get-Content $_.PSPath |
ForEach {$ -creplace "old", "new"}) | Set-Content $_.PSPath }
这将用“新”替换当前目录下文件夹中所有文件中的所有“旧”区分大小写。请告诉我们您的进展情况,或者需要解决的文件是否存在一些奇怪的格式问题。这个问题的一个好处是它的测试不会影响生产代码。我想补充一点,测试提供的所有解决方案都是可行的,但这一个是最容易实现可读性的。我可以把这个交给一个同事,他可以很容易地理解发生了什么。感谢您的帮助。要在子目录中的文件中工作,您需要“.PSPath”。有趣的是,当我尝试在没有()的情况下使用get content时,它在写入内容时失败了,因为文件被锁定。短版本(使用了常见别名):
ls*.config-rec |%{$f=$};(gc$f.PSPath)|%{$}替换“Dev”,“Demo”}sc$f.PSPath}
@Artyom不要忘记ls
之后的
。我自己也被刺痛了。如果您要删除*.config以在所有文件上运行,UnauthorizedAccessException也可能由于文件夹而导致。您可以将-File筛选器添加到Get-ChildItem。。。我花了一段时间才弄明白,如果其他人遇到这个问题,就像我所做的那样——直接从批处理文件执行这个问题——在执行这样的命令时,使用foreach对象
而不是%
别名可能会有所帮助。否则,它可能会导致错误:表达式只允许作为管道的第一个元素
答案中的“.PSPath”部分确实帮助了我。但我必须将内部的“{$”更改为“$\”.我会编辑你的答案,但我没有使用你的-creplace部分--我使用的是接受的答案与.pspath一起使用,因此为了简洁表达,我选择了这个答案-但我必须将Get Content$\ucode>替换为Get Content$\ucode>。FullName
,以及Set Content
的等效项,以处理不在根目录下的文件。