
Welcome PowerShell User! This recipe is just one of the hundreds of useful resources contained in the PowerShell Cookbook.
If you own the book already, login here to get free, online, searchable access to the entire book's content.
If not, the Windows PowerShell Cookbook is available at Amazon, or any of your other favourite book retailers. If you want to see what the PowerShell Cookbook has to offer, enjoy this free 90 page e-book sample: "The Windows PowerShell Interactive Shell".
You want to find a string or regular expression in a file.
To search a file for an exact (but case-insensitive) match, use the -Simple parameter of the Select-String cmdlet:
Select-String -Simple SearchText file.txt
To search a file for a regular expression, provide that pattern to the Select-String cmdlet:
Select-String "\(...\) ...-...." phone.txt
To recursively search all *.txt files for a regular expression, pipe the results of Get-ChildItem to the Select-String cmdlet:
Get-ChildItem *.txt -Recurse | Select-String pattern
Or, using built-in aliases:
dir *.txt -rec | sls pattern
The Select-String cmdlet is the easiest way to search files for a pattern or specific string. In contrast to the traditional text-matching utilities (such as grep) that support the same type of functionality, the matches returned by the Select-String cmdlet include detailed information about the match itself:
PS > $matches = Select-String "output file" transcript.txt
PS > $matches | Select LineNumber,Line
LineNumber Line
---------- ----
7 Transcript started, output file...
With a regular expression match, you’ll often want to find out exactly what text was matched by the regular expression. PowerShell captures this in the Matches property of the result. For each match, the Value property represents the text matched by your pattern:
PS > Select-String "\(...\) ...-...." phone.txt | Select -Expand Matches ... Value : (425) 555-1212 ... Value : (416) 556-1213
If your regular expression defines groups (portions of the pattern enclosed in parentheses), you can access the text matched by those groups through the Groups property. The first group (Group[0]) represents all of the text matched by your pattern. Additional groups (1 and on) represent the groups you defined. In this case, we add additional parentheses around the area code to capture it:
PS > Select-String "\((...)\) ...-...." phone.txt |
Select -Expand Matches | Foreach { $_.Groups[1] }
Success : True
Captures : {425}
Index : 1
Length : 3
Value : 425
Success : True
Captures : {416}
Index : 1
Length : 3
Value : 416
If your regular expression defines a named capture (with the text ?<Name> at the beginning of a group), the Groups collection lets you access those by name. In this example, we capture the area code using AreaCode as the capture name:
PS > Select-String "\((?<AreaCode>...)\) ...-...." phone.txt |
Select -Expand Matches | Foreach { $_.Groups["AreaCode"] }
Success : True
Captures : {425}
Index : 1
Length : 3
Value : 425
Success : True
Captures : {416}
Index : 1
Length : 3
Value : 416
By default, the Select-String cmdlet captures only the first match per line of input. If the input can have multiple matches per line, use the -AllMatches parameter:
PS > Get-Content phone.txt
(425) 555-1212
(416) 556-1213 (416) 557-1214
PS > Select-String "\((...)\) ...-...." phone.txt |
Select -Expand Matches | Select -Expand Value
(425) 555-1212
(416) 556-1213
PS > Select-String "\((...)\) ...-...." phone.txt -AllMatches |
Select -Expand Matches | Select -Expand Value
(425) 555-1212
(416) 556-1213
(416) 557-1214
For more information about captures, named captures, and other aspects of regular expressions, see Appendix B.
If the information you need is on a different line than the line that has the match, use the -Context parameter to have that line included in Select-String’s output. PowerShell places the result in the Context.PreContext and Context.PostContext properties of Select-String’s output.
If you want to search multiple files of a specific extension, the Select-String cmdlet lets you use wildcards (such as *.txt) on the filename. For more complicated lists of files (which includes searching all files in the directory), it is usually better to use the Get-ChildItem cmdlet to generate the list of files as shown previously in the Solution.
Since the Select-String cmdlet outputs the filename, line number, and matching line for every match it finds, this output may sometimes include too much detail. A perfect example is when you are searching for a binary file that contains a specific string. A binary file (such as a DLL or EXE) rarely makes sense when displayed as text, so your screen quickly fills with apparent garbage.
The solution to this problem comes from Select-String’s -Quiet switch. It simply returns true or false, depending on whether the file contains the string. So, to find the DLL or EXE in the current directory that contains the text “Debug”:
Get-ChildItem|Where{$_|Select-String"Debug"-Quiet}
Two other common tools used to search files for text are the -match operator and the switch statement with the -file option. For more information about those, see Recipe 5.7 and Recipe 4.3. For more information about the Select-String cmdlet, type Get-Help Select-String.
Recipe 4.3, “Manage Large Conditional Statements with Switches”
Recipe 5.7, “Search a String for Text or a Pattern”
Appendix B, Regular Expression Reference