用于查找和替换具有特定扩展名的所有文件的PowerShell脚本

时间:2010-05-14 21:36:13

标签: powershell scripting replace find

我在Windows Server 2008上有几个配置文件,如下所示:

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大师?

8 个答案:

答案 0 :(得分:155)

这是我头脑中的第一次尝试。

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

答案 1 :(得分:29)

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"))
    }

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

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

答案 2 :(得分:14)

这种方法效果很好:

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

答案 3 :(得分:9)

我会使用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)  
}

答案 4 :(得分:7)

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

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

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

答案 5 :(得分:6)

此powershell示例查找字符串&#34; \ foo \&#34;的所有实例。在一个文件夹及其子文件夹中,替换&#34; \ foo \&#34;用&#34; \ bar \&#34;并且不会重写不包含字符串&#34; \ foo \&#34;的文件。这样您就不会破坏文件的最后更新日期时间标记,其中找不到字符串:

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 $_ }
           }

答案 6 :(得分:5)

我编写了一个小帮助函数来替换文件中的文本:

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' 
}

答案 7 :(得分:4)

进行递归替换时,需要包含路径和文件名:

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

这将取代所有&#34; old&#34;用&#34; new&#34;在当前目录的文件夹的所有文件中区分大小写。