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スクリプトを使用すると、簡単に実行できると聞きました。検索/置換の例を見つけましたが、C:\ Projectsディレクトリ内のすべてのフォルダーを走査し、拡張子が「.config」で終わるファイルを見つける方法を探していました。見つかったら、文字列値を置き換えてほしい。
これを行う方法や、洞察を提供できるPowerShellの達人を見つけるための良いリソースはありますか?
ここで私の頭の上の最初の試み。
$configFiles = Get-ChildItem . *.config -rec
foreach ($file in $configFiles)
{
(Get-Content $file.PSPath) |
Foreach-Object { $_ -replace "Dev", "Demo" } |
Set-Content $file.PSPath
}
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"))
}
読みやすいようにコードを複数の行に分割します。 [IO.File]::WriteAllText
の代わりにSet-Contentを使用できますが、最後に新しい行が追加されることに注意してください。 WriteAllText
を使用すると、回避できます。
それ以外の場合、コードは$c | Set-Content $_.FullName
のようになります。
このアプローチはうまく機能します。
gci C:\Projects *.config -recurse | ForEach {
(Get-Content $_ | ForEach {$_ -replace "old", "new"}) | Set-Content $_
}
私は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の例では、フォルダーとそのサブフォルダー内の文字列「\ foo \」のすべてのインスタンスを検索し、「\ foo \」を「\ bar \」に置き換え、文字列「\ foo \を含まないファイルを書き換えません"この方法では、文字列が見つからなかったファイルの最終更新日時スタンプを破棄しません。
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 $_ }
}
@ Artyom のコメントを見つけましたが、残念ながら彼は答えを投稿していません。
私の意見では、これは受け入れられた答えの短いバージョンです。
ls *.config -rec | %{$f=$_; (gc $f.PSPath) | %{$_ -replace "Dev", "Demo"} | sc $f.PSPath}
ファイル内のテキストを置き換えるための小さなヘルパー関数を作成しました。
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'
}
再帰的な置換を行う場合、パスとファイル名を含める必要があります。
Get-ChildItem -Recurse | ForEach { (Get-Content $_.PSPath |
ForEach {$ -creplace "old", "new"}) | Set-Content $_.PSPath }
これは、現在のディレクトリのフォルダのすべてのファイルで、大文字と小文字を区別するすべての「古い」を「新しい」に置き換えます。