Paulo
Paulo

Reputation: 361

Powershell Set Content Replaced string

So, i need to save a string that was replaced on files.

I'm doing something wrong, but i`m not be able to figure it out, what!

My code:

    Get-ChildItem -Path C:\Users\user\Documents -Recurse -Include "*.txt" -File |  Select-String  -Pattern \b192\.168\.10\.2\b , \b192\.168\.10\.11\b -AllMatches -List |  Foreach-Object { $_ -replace '\b192\.168\.10\.2\b', "DEV" -and $_ -replace '\b192\.168\.10\.11\b', "QUAL" | Set-Content $_}

And gives-me the following error:

   Set-Content : Could not open the alternate data stream '1:192.168.10.11' of the file 'C:\Users\user\Documents\result.txt'.
   At line:1 char:323
   + ... place '\b192\.168\.10\.11\b', "QUAL" | Set-Content $_}
   +                                                         
   + CategoryInfo : ObjectNotFound: (C:\Users\paulo....ents\result.txt:String) [Set-Content], FileNotFoundException
   + FullyQualifiedErrorId :  GetContentWriterFileNotFoundError,Microsoft.PowerShell.Commands.SetContentCommand

   Set-Content : Could not open the alternate data stream '1:192.168.10.11' of the file 
  'C:\Users\user\Documents\test.txt'
   At line:1 char:323 ... place '\b192\.168\.10\.11\b', "QUAL" | Set-Content $_}                                                             
   CategoryInfo : ObjectNotFound: (C:\Users\user\test.txt:String) [Set-Content], FileNotFoundException
   FullyQualifiedErrorId : GetContentWriterFileNotFoundError,Microsoft.PowerShell.Commands.SetContentCommand

Thanks for any Help!

Upvotes: 1

Views: 395

Answers (2)

Theo
Theo

Reputation: 61068

The -and operator is used inside if tests like if(this -and that).
You should change the double replace actions from

$_ -replace '\b192\.168\.10\.2\b', "DEV" -and $_ -replace '\b192\.168\.10\.11\b', "QUAL"

into

$_ -replace '\b192\.168\.10\.2\b', "DEV" -replace '\b192\.168\.10\.11\b', "QUAL"

Also, if I understand the question properly, you want to find all string replacements in the file, and to get all, you need to remove the -List switch from Select-String.

Next, as Mathias explains in his answer, you need to use the Path property from the current match to get the file FullName.
However, if you pipe this through to Set-Content straight away, you will get an exception because the file then is in use and you cannot write to the same file.

Below creates a new file in the same path, with _replacements appended to the filename

# use '-Include' instead of '-Filter' if you need more file extensions to filter on
Get-ChildItem -Path 'C:\Users\user\Documents' -Recurse -Filter "*.txt" -File |  
Select-String  -Pattern '\b192\.168\.10\.2\b', '\b192\.168\.10\.11\b' -AllMatches |  
Foreach-Object { 
    $file = '{0}_replacements{1}' -f [System.IO.Path]::GetFileNameWithoutExtension($_.Path),
                                     [System.IO.Path]::GetExtension($_.Path)
    $target = Join-Path -Path ([System.IO.Path]::GetDirectoryName($_.Path)) -ChildPath $file
    $_ -replace '\b192\.168\.10\.2\b', "DEV" -replace '\b192\.168\.10\.11\b', "QUAL"  | 
    Add-Content -Path $target 
}

This results in a file called 'C:\Users\user\Documents\test_replacements.txt'

C:\Users\user\Documents\test.txt:4:DEV
C:\Users\user\Documents\test.txt:7:QUAL

The original file 'C:\Users\user\Documents\test.txt' will not be altered.

Upvotes: 2

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174485

Inside the ForEach-Object block, $_ will refer to the current match result as returned by Select-String - to get the file path, reference the Path property:

... | ForEach-Object { ... |Set-Content -LiteralPath $_.Path}

Upvotes: 2

Related Questions