Home > Software design >  How can i search for multiple string patterns in text files within a directory
How can i search for multiple string patterns in text files within a directory

Time:04-12

I have a textbox that takes an input and searches a drive.

Drive for example is C:/users/me

let's say I have multiple files and subdirectories in there and I would like to search if the following strings exist in the file: "ssn" and "DOB"

Once user inputs the two strings. I split the string but space, so I can loop through the array. But here is my current code, but I'm stuck on how to proceed.

  gci "C:\Users\me" -Recurse | where { ($_ | Select-String -pattern ('SSN') -SimpleMatch) -or ($_ | Select-String -pattern ('DOB') -SimpleMatch ) } | ft CreationTime, Name -Wrap -GroupBy Directory | Out-String

this above code works if i pasted it manually into powershell but I'm trying to recreate this in a script but having confusion and how to do so.

this code below is not getting all the files needed.

foreach ($x in $StringArrayInputs) {
           if($x -eq $lastItem){
                $whereClause = ($_  | Select-String -Pattern $x)
            }else{
                $whereClause = ($_ | Select-String -Pattern $x)   '-or'
            } 
            $files= gci $dv -Recurse | Where { $_ | Select-String -Pattern $x -SimpleMatch} | ft CreationTime, Name -Wrap -GroupBy Directory | Out-String
}

CodePudding user response:

I just followed your examples and combined both with a regex. I escaped the regex to avoid accidential usage of expressions (like a dot for any char).

It is working with my testfiles but may differ with your files. You may need to add " -Encoding UTF8" with your appropriate encoding so you may get regional specific chars as well.

$String = Read-Host "Enter multiple strings seperated by space to search for"
$escapedRegex = ([Regex]::Escape($String)) -replace "\\ ","|"

Get-ChildItem -Recurse -Attributes !Directory | Where-Object {
    $_ | Get-Content | Select-String -Pattern $escapedRegex
} | Format-Table CreationTime, Name -Wrap -GroupBy Directory | Out-String

CodePudding user response:

Select-String's -Pattern parameter accepts an array of strings (any one of which triggers a match), so piping directly to a single Select-String call should do:

$files= Get-ChildItem -File -Recurse $dv | 
          Select-String -List -SimpleMatch -Pattern $StringArrayInputs } |
            Get-Item |
              Format-Table CreationTime, Name -Wrap -GroupBy Directory |               
                Out-String

Note:

  • Using -File with Get-ChildItem makes it return only files, not also directories.

  • Using -List with Select-String is an optimization that ensures that at most one match per file is looked for and reported.

  • Passing Select-String's output to Get-Item automatically binds the .Path property of the former's output to the -Path parameter of the latter.

    • Strictly speaking, binding to -Path subjects the argument to interpretation as a wildcard expression, which, however, is generally not a concern - except if the path contains [ characters.
    • If that is a possibility, insert a pipeline segment with Select-Object @{ Name='LiteralPath'; Expression='Path' } before Get-Item, which ensures binding to -LiteralPath instead.
  • Related