Script PowerShell pour rechercher et remplacer tous les fichiers avec une extension spécifique

J’ai plusieurs fichiers de configuration sur Windows Server 2008 nesteds comme suit:

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

Dans ma configuration, je dois faire un remplacement de chaîne comme ceci:

  

va devenir:

  

J’ai pensé à utiliser les scripts par lot, mais il n’y avait pas de moyen de le faire, et j’ai entendu dire qu’avec les scripts PowerShell, vous pouvez facilement effectuer cela. J’ai trouvé des exemples de find / replace, mais j’espérais un moyen de parcourir tous les dossiers de mon répertoire C: \ Projects et de trouver tous les fichiers se terminant par l’extension ‘.config’. Quand il en trouve un, je veux qu’il remplace mes valeurs de chaîne.

De bonnes ressources pour savoir comment faire ceci ou n’importe quel gourou PowerShell qui peut vous donner un aperçu?

Voici une première tentative en tête.

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

PowerShell est un bon choix;) Il est très facile d’énumérer des fichiers dans un répertoire donné, de les lire et de les traiter.

Le script pourrait ressembler à ceci:

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

Je divise le code en plusieurs lignes pour être lisible pour vous. Notez que vous pouvez utiliser Set-Content au lieu de [IO.File]::WriteAllText , mais il ajoute une nouvelle ligne à la fin. Avec WriteAllText vous pouvez l’éviter.

Sinon, le code pourrait ressembler à ceci: $c | Set-Content $_.FullName $c | Set-Content $_.FullName .

Cette approche fonctionne bien:

 gci C:\Projects *.config -recurse | ForEach { (Get-Content $_ | ForEach {$_ -replace "old", "new"}) | Set-Content $_ } 
  • Changer “vieux” et “nouveau” à leurs valeurs correspondantes (ou utiliser des variables).
  • N’oubliez pas la parenthèse – sans laquelle vous recevrez une erreur d’access.

Je voudrais aller avec xml et 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) } 

Cet exemple de PowerShell recherche toutes les instances de la chaîne “\ foo \” dans un dossier et ses sous-dossiers, remplace “\ foo \” par “\ bar \” ET NE RERIRE PAS les fichiers qui ne contiennent pas la chaîne “\ foo \ “De cette façon, vous ne détruisez pas le dernier fichier de mise à jour datetime où la chaîne n’a pas été trouvée:

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

J’ai écrit une petite fonction d’aide pour remplacer du texte dans un fichier:

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

Exemple:

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

J’ai trouvé le commentaire de @Artyom utile mais malheureusement il n’a pas posté de réponse.

C’est la version courte, à mon avis la meilleure version de la réponse acceptée;

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

Lors du remplacement récursif, le chemin et le nom du fichier doivent être inclus:

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

Cela remplacera tous les “anciens” par les “nouveaux” sensibles à la casse dans tous les fichiers de vos dossiers de votre répertoire actuel.