Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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    
}
like image 274
Jagannath Avatar asked May 28 '13 23:05

Jagannath


People also ask

How do you use the Replace function in PowerShell?

You can call the PowerShell replace method on any string to replace any literal string with another. If the string-to-be-replaced isn't found, the replace() method returns nothing. You don't need to assign a string to a variable to replace text in a string.

How do you replace content in PowerShell?

One way to do that is to use the Set-Content command. The Set-Content command replaces all contents of a file with assigning a new value. Whenever you now read the C:\file. txt file with Get-Content , you'll see that it now contains the new content.

How do I replace a string in PowerShell?

In PowerShell we can use the Replace() method on any string or variable that is a string. The method needs two arguments, the text or character that you want to find and the with what you want to replace it with.


2 Answers

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.

like image 119
Andy Arismendi Avatar answered Nov 15 '22 10:11

Andy Arismendi


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 }
like image 42
EddieRock Avatar answered Nov 15 '22 10:11

EddieRock