Powershell how to get-content across several subfolders

Viewed 123

I'm working on a script to output some data from multiple files based on a string search. It outputs the string found, followed by the following six characters. I can get this to work for an exact location. However, I want to search across files inside multiple subfolders in the path. Using the below script, I get PermissionDenied errors...

[regex] $pattern = '(?<=(a piece of text))(?<chunk>.*)'
Get-Content -Path 'C:\Temp\*' |
ForEach-Object {
  if ($_ -match $pattern) {
    $smallchunk = $matches.chunk.substring(0, 6)
  }
}
    
"$smallchunk" | Out-File  'C:\Temp\results.txt'

If I change -Path to one of the subfolders, it works fine, but I need it to go inside each subfolder and execute the get-content.

e.g., look inside...

C:\Temp\folder1\*
C:\Temp\folder2\*
C:\Temp\folder3\*

And so on...

2 Answers

Following up on boxdog's suggestion of Select-String, the only limitation would be folder recursion. Unfortunately, Select-String only allows the searching of multiple files in one directory.

So, the way around this is piping the output of Get-ChildItem with a -Recurse switch into Select-String:

$pattern = "(?<=(a piece of text))(?<chunk>.*)"
Get-ChildItem -Path "C:\Temp\" -Exclude "results.txt" -File -Recurse | 
    Select-String -Pattern $pattern |
    ForEach-Object -Process {
        $_.Matches[0].Groups['chunk'].Value.Substring(0,6)
    } | Out-File -FilePath "C:\Temp\results.txt"

If there's a need for the result to be saved to $smallchunk you can still do so inside the loop if need be.

Abraham Zinala's helpful answer is the best solution to your problem, because letting Select-String search your files' content is faster and more memory-efficient than reading and processing each line with Get-Content.


As for what you tried:

Using the below script I get PermissionDenied errors...

These stem from directories being among the file-system items output by Get-ChildItem, which Get-Content cannot read.

If your files have distinct filename extensions that your directories don't, one option is to pass them to the (rarely used with Get-Content) -Include parameter; e.g.:

Get-Content -Path C:\Temp\* -Include *.txt, *.c 

However, as with Select-String, this limits you to a single directory's content, and it doesn't allow you to limit processing to files fundamentally, if extension-based filtering isn't possible.

For recursive listing, you can use Get-ChildItem with -Recurse, as in Abraham's answer, and pipe the file-info objects to Get-Content:

Get-ChildItem -Recurse C:\Temp -Include *.txt, *.c | Get-Content

If you want to simply limit output to files, whatever their name is, use the -File switch (similarly, -Directory limits output to directories):

Get-ChildItem -File -Recurse C:\Temp | Get-Content
Related