Home > Back-end >  Find lines with specific characters recursively
Find lines with specific characters recursively

Time:12-06

I am searching for all lines with '.png' and '.jpg' strings in them across multiple folders of TXT files.

Tried:

   (Get-ChildItem K:\FILES -Recurse -Include '*.txt') | ForEach-Object {
    (Get-Content $_) -match '\.png','\.jpg' | out-file K:\Output.txt
   }

but it does not output anything. No error either. I did something similar recently and it was working. I am scratching my head wondering what am I doing wrong here...

CodePudding user response:

By placing your Out-File call inside the ForEach-Object script block, you're rewriting your output file in full for every input file, so that the last input file's results - which may be none - end up as the sole content of the file.

The immediate fix is to move the Out-File call to its own pipeline segment, so that it receives all output, across all files:

Get-ChildItem K:\FILES -Recurse -Include '*.txt' | 
  ForEach-Object {
    @(Get-Content $_) -match '\.png', '\.jpg'
  } |
  Out-File K:\Output.txt

Note: Technically, adding -Append to your Out-File call inside the ForEach-Object could have worked too, but this approach should be avoided:

  • Every Out-File call must open and close the output file, which makes the operation much slower.

  • You need to ensure that there is no preexisting output file beforehand - otherwise you'll end up appending to that file's existing content.


However, consider speeding up your command with the help of Select-String:

Get-ChildItem K:\FILES -Recurse -Include '*.txt' | 
  Select-String -Pattern '\.png', '\.jpg' |
  ForEach-Object Line |
  Out-File K:\Output.txt

Note:

  • In PowerShell (Core) 7 , you can use the -Raw switch with Select-String, which directly outputs only the text of all matching lines, in which case ForEach-Object Line isn't needed.
  • Related