Jagannath
Jagannath

Reputation: 4025

In place replace using powershell

I am trying to write an equivalent of

find -name "*.xml" | xargs grep -l "Search String" 
       | xargs perl -p -i -e 's/Search String/Replace String/g'

in powershell. This is what I came up with.

Get-ChildItem 'D:\code\cpp\FileHandlingCpp\input - Copy' -Recurse |
Select-String -SimpleMatch $src_str | 
foreach{(Get-Content $_.path) | ForEach-Object { $_ -replace $src_str, $target_str }}

I get the error "The process cannot access the file because it is being used by another process”. So I came up with the multiple lines version as shown below. I am able to do in-replace of the strings now except the one in $src_str. What's wrong with $src_str ?

$src_str="<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes"" ?>"
$target_str=""
echo $src_str

foreach ($var in (Get-ChildItem 'D:\code\cpp\FileHandlingCpp\input - Copy' -Recurse 
                     | Select-String -SimpleMatch $src_str).Path) 
{    
  (Get-Content $var) | ForEach-Object { $_ -replace $src_str, $target_str }
    | Set-Content $var    
}

Upvotes: 7

Views: 5357

Answers (2)

EddieRock
EddieRock

Reputation: 51

This took me a while to figure out but I got it!

It's a one liner. Just go to the folder you want to start at and type this in. Change the file.name (use wild cards if you want) and string1 and string2 with the file name you want to search for and the string1 you want to replace with string2.

So this searches folders recursivly and for each file it replaces a string with another string and saves it. Basically Get-Childitem | ForEach-Object Replace and Save.

All set!

get-childitem -include file.name -Recurse | ForEach-Object { ( Get-Content -Path $_.FullName ) -replace 'string1', 'string2' | set-content $_.fullname }

Upvotes: 5

Andy Arismendi
Andy Arismendi

Reputation: 52619

Maybe it would help to get back to your original goal of implementing the equivalent of the Unix version. Here is essentially the equivalent PowerShell version.

$search = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>'
$replace = 'test'
$dir = 'D:\code\cpp\FileHandlingCpp\input - Copy'

dir -Path $dir -Recurse -Filter *.xml | ForEach-Object {
    (Get-Content -Path $_.FullName) -replace $search, $replace | 
        Set-Content $_.FullName
}

Note - watch out for text file encoding changes that may occur from re-writing the file. You can specify the output encoding if you need to using Set-Content's -Encoding parameter e.g. ASCII.

Upvotes: 12

Related Questions