2

I'm trying to replicate this command into PowerShell:

grep -lR 'Find' ./src | while read filename; do sed -i".bak" 's/Find/Replace/g' "$filename"; done 

What I have so far:

Get-ChildItem "src" -Recurse -File | ForEach-Object { $f = $_; (Get-Content $f) | ForEach-Object { $_ -replace "Find", "Replace" } | Set-Content "$f.tmp"; Move-Item "$f.tmp" $f -Force }

I'm getting an error saying "filename.tmp" does not exist. I thought the above would create the file while parsing. Any help would be appreciated.

Milk
  • 2,469
  • 5
  • 31
  • 54

1 Answers1

2

Most likely you've fallen victim to Windows PowerShell's inconsistent stringification of the System.IO.FileInfo instances output by Get-ChildItem - see this answer.

The workaround is to use explicit stringification via the .FullName property, which explicitly returns an item's full path.

Applied to your command, alongside some optimizations:

Get-ChildItem -File -Recurse src | ForEach-Object { 
   $f = $_.FullName  # !! Explicitly retrieve the full path
   (Get-Content $f -Raw) -creplace 'Find', 'Replace' | 
     Set-Content -NoNewline "$f.tmp"
   Move-Item "$f.tmp" $f -Force
}
  • Get-Content -Raw reads the entire file into memory as a single string, which is more efficient.

  • -creplace (which performs case-sensitive replacement, as sed would by default) is directly applied to the resulting multiline string and replaces all occurrences.

  • -NoNewline (PSv5+) ensures that Set-Content doesn't add an additional trailing newline to the multiline string being saved (the same applies to Out-File / >).

  • Note: Given that Get-Content -Raw reads the entire file up front, you could even write the modified content back to the very same file, without requiring an intermediate temporary file and a subsequent Move-Item call; that said, doing so bears a slight risk of data loss, if the process of writing back to the same file is interrupted.

    • Also, while your sed call retains the original file with extension .bak, your PowerShell command does not.
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Glad to hear it was helpful, @Milk; my pleasure. Good point re `-NoNewline` - I've added it to the answer, along with an explanation. – mklement0 Mar 14 '19 at 19:44