Home > Back-end >  Powershell how to get-content across several subfolders
Powershell how to get-content across several subfolders

Time:06-09

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 next 6 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 {
    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 perform the get-content.

e.g. look inside..

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

and so on...

CodePudding user response:

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

CodePudding user response:

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.

  • Related