Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell Script to Find and Replace for all Files with a Specific Extension

People also ask

How do I change the extension of multiple files in PowerShell?

Change file extensions with PowerShell You can also use the Rename-Item to change file extensions. If you want to change the extensions of multiple files at once, use the Rename-Item cmdlet with the Get-ChildItem cmdlet.

How do I find and replace in all files?

Remove all the files you don't want to edit by selecting them and pressing DEL, then right-click the remaining files and choose Open all. Now go to Search > Replace or press CTRL+H, which will launch the Replace menu. Here you'll find an option to Replace All in All Opened Documents.

How do I replace a file in PowerShell?

Use Get-Content and Set-Content to Replace Every Occurrence of a String in a File With PowerShell. The Get-Content gets the item's content in the specified path, such as the text in a file. The Set-Content is a string-processing cmdlet that allows you to write new content or replace the existing content in a file.


Here a first attempt at the top of my head.

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

PowerShell is a good choice ;) It is very easy to enumerate files in given directory, read them and process.

The script could look like this:

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

I split the code to more lines to be readable for you. Note that you could use Set-Content instead of [IO.File]::WriteAllText, but it adds new line at the end. With WriteAllText you can avoid it.

Otherwise the code could look like this: $c | Set-Content $_.FullName.


This approach works well:

gci C:\Projects *.config -recurse | ForEach {
  (Get-Content $_ | ForEach {$_ -replace "old", "new"}) | Set-Content $_ 
}
  • Change "old" and "new" to their corresponding values (or use variables).
  • Don't forget the parenthesis -- without which you will receive an access error.

I would go with xml and 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)  
}

This powershell example looks for all instances of the string "\foo\" in a folder and its subfolders, replaces "\foo\" with "\bar\" AND DOES NOT REWRITE files that don't contain the string "\foo\" This way you don't destroy the file last update datetime stamps where the string was not found:

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