2

The following snippet extracts only the matching lines, I also want the path and line number:

Get-ChildItem $thePath\ -Include "*.txt" -Recurse | Get-Content | Select-String  -Pattern 'THE_PATTEN' | Set-Content "output.txt"

I tried with this method and still it only extracts the matching lines:

Get-ChildItem $thePath\ -Include "*.txt" -Recurse | Get-Content | Select-String  -Pattern 'THE_PATTEN' | Select-Object -ExpandProperty Line | Set-Content "output.txt"

How can I extract the path:filename:line number: matching line?

Sherzad
  • 405
  • 4
  • 14

3 Answers3

2

You don't need get-content. The path is passed over the pipe. (. is for -path, and *.txt is for -filter for speed)

get-childitem -recurse . *.txt | select-string hi

foo2\file3.txt:1:hi
file1.txt:1:hi
file2.txt:1:hi
js2010
  • 23,033
  • 6
  • 64
  • 66
1

Yea, you can get line number and file name from the output of Select-String:

ls *.txt | % { Select-String -Path $_ -Pattern "THE_PATTERN" | select-object LineNumber, Line, Path }

You'll notice this approach is also a touch faster.

Good luck!

Adam
  • 3,891
  • 3
  • 19
  • 42
  • Actually, the filename and line number are included in the default output view as pointed out here: https://stackoverflow.com/a/59582116/408817 – Glenn Jan 03 '20 at 19:38
  • @Glenn it looks like you've linked back to this post? – Adam Jan 04 '20 at 01:25
  • @AbdulRahmanSherzad, Tobias Weltner had a dope presentation on the performance impacts of reading data and passing it through pipes. Of course, I can't find it to share. Net-net, there was a performance penalty to using pipes. The benefit I was referencing related to piping to fewer command lets. – Adam Jan 07 '20 at 16:20
1

First note that Get-ChildItem -Filter is way more efficient than Get-ChildItem -Include (see help get-childitem). Next is that Select-String accepts files. No need to get the content first. Now just Select the properties you need and export your file. (Note that the variable $match and $matches are system variables so you might not want to use them.)

$Patterns = Get-ChildItem $thePath -Filter "*.txt" -Recurse| Select-String  -Pattern 'THE_PATTEN' | select Path,Filename,LineNumber,Line

# Export to csv (usable in excel)
$Patterns | Export-Csv output.csv -NoTypeInformation # -Delimiter ";" #  the delimiter is optinal and depending of your region

# Exporting txt
foreach ($Pattern in $Patterns){
    ('{0} : {1} : {2}' -f ($Pattern.Path),($Pattern.LineNumber),($Pattern.Line)) | Add-Content "output.txt"
}
T-Me
  • 1,814
  • 1
  • 9
  • 22
  • Thank you:-) However, inside the **foreach** we must **Add-Content** because the **Set-Content** writes new content or replaces the existing content of the file. – Sherzad Jan 04 '20 at 07:55
  • If the **-AllMatches** is used with the **Select-String** like this `$Patterns = Get-ChildItem $thePath -Filter "*.txt" -Recurse| Select-String -Pattern 'THE_PATTEN' -AllMatches | select Matches,Path,Filename,LineNumber,Line`. Then how we can handle it with the **Export-Csv** command. With **foreach** it is possible to achieve the matches by using another nested **foreach** for the matches. However, I want to know if it is possible with the **Export-Csv** command. – Sherzad Jan 04 '20 at 08:00
  • @AbdulRahmanSherzad edited to change `Set-Conent` to `Add-Content` as you sugested. What kind of behaviour do you want for `-AllMatches`? Currently when you set the parameter it finds multiple occurrences of the pattern per line but it will just output the line once. Do you want to add a column for the count or to add the line multiple times for each occurrence? – T-Me Jan 06 '20 at 11:10
  • I want both the line and the column. I could manage it using nested loops, however, I want to know if it is feasible using the **Export-Csv** command. Following works perfect: `foreach ($the_pattern in $Patterns) { foreach ($the_match in $the_pattern.Matches) { ('{0};{1};{2};{3};{4}' -f ($the_match -replace "[^0-9]"), ($the_match),($the_pattern.LineNumber),($the_pattern.Path), ($the_pattern.Line)) | Add-Content $output_file } }` – Sherzad Jan 06 '20 at 12:21