45

I would like to search for more than one string in the files in a directory, however using "select-string -pattern" didn't help. Could anyone show me how to do it?

Example: Search all files in C:\Logs that contain the words "VendorEnquiry" and "Failed", and with a Logtime about 11:30 am. Structure of files may differ (e.g. different tag names, etc):

... <methodException>VendorEnquiry</methodException> ...
... <logTime>13/10/2010T11:30:04 am</logTime> ...
... <status>Failed</status> ...

... <serviceMethodException>VendorEnquiry</serviceMethodException> ...
... <logTime>13/10/2010</logTime> ...
... <serviceStatus>Failed</serviceStatus> ...

Thanks.

3 Answers 3

45

If you want to match the two words in either order, use:

gci C:\Logs| select-string -pattern '(VendorEnquiry.*Failed)|(Failed.*VendorEnquiry)'

If Failed always comes after VendorEnquiry on the line, just use:

gci C:\Logs| select-string -pattern '(VendorEnquiry.*Failed)'
Sign up to request clarification or add additional context in comments.

Comments

35

To search for multiple matches in each file, we can sequence several Select-String calls:

Get-ChildItem C:\Logs |
  where { $_ | Select-String -Pattern 'VendorEnquiry' } |
  where { $_ | Select-String -Pattern 'Failed' } |
  ...

At each step, files that do not contain the current pattern will be filtered out, ensuring that the final list of files contains all of the search terms.

Rather than writing out each Select-String call manually, we can simplify this with a filter to match multiple patterns:

filter MultiSelect-String( [string[]]$Patterns ) {
  # Check the current item against all patterns.
  foreach( $Pattern in $Patterns ) {
    # If one of the patterns does not match, skip the item.
    $matched = @($_ | Select-String -Pattern $Pattern)
    if( -not $matched ) {
      return
    }
  }

  # If all patterns matched, pass the item through.
  $_
}

Get-ChildItem C:\Logs | MultiSelect-String 'VendorEnquiry','Failed',...


Now, to satisfy the "Logtime about 11:30 am" part of the example would require finding the log time corresponding to each failure entry. How to do this is highly dependent on the actual structure of the files, but testing for "about" is relatively simple:

function AboutTime( [DateTime]$time, [DateTime]$target, [TimeSpan]$epsilon ) {
  $time -le ($target + $epsilon) -and $time -ge ($target - $epsilon)
}

PS> $epsilon = [TimeSpan]::FromMinutes(5)
PS> $target = [DateTime]'11:30am'
PS> AboutTime '11:00am' $target $epsilon
False
PS> AboutTime '11:28am' $target $epsilon
True
PS> AboutTime '11:35am' $target $epsilon
True

Comments

32

You can specify multiple patterns in an array:

Select-String -Pattern 'VendorEnquiry', 'Failed' -LiteralPath "$Env:SystemDrive\Logs"

This works with -NotMatch as well:

Select-String -NotMatch 'VendorEnquiry', 'Failed' -LiteralPath "$Env:SystemDrive\Logs"

5 Comments

Agreed. This worked perfectly for me and much simpler than the other answers
Yeah, my answers get deleted or marked down by some, and marked up by others.
I was going to say that the other posters had included something more specifically geared towards the original question ... but not really. They did a great job explaining the use of the command, but so what? The original question is a problem because it's vague, so the answers could be anything, really. This answer is as good as any, regarding the question, I guess I'm saying.
This lists files with OR relations between elements. That is if a file has just "VendorEnquiry" , it will list it. How to look for files that much have both "VendorEnquiry" and "Failed"? In other words, AND relation between elements of the pattern array.
@qqqqq I suppose you can do get-content file | select-string pattern1 | select-string pattern2, get-content -raw for all strings at once.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.