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