The grep command is widely used on Linux to parse files and shell output. Using grep you can easily find and filter the output returned by the previous command in the pipeline. In this article, we’ll take a look at the equivalents of the grep command in Windows PowerShell.
Hint. If you have WSL (Windows Subsystem for Linux) installed on your computer, you can use the native grep command directly in your scripts. For example, to run the Linux grep utility in a PowerShell console, use the following syntax:
dir | wsl grep something
All commands you pass to wsl.exe will be redirected to the WSL process unchanged. Note that you must use the WSL file path format.
On the Windows Command Line (CMD), the equivalent to grep is findstr. However, it is difficult to use it in PowerShell scripts. The simplest PowerShell equivalent to grep is Select-String.
The Select-String cmdlet provides the following features:
- Search by regular expressions (default);
- Search by literal match (the parameter -Simple);
- Search only the first match in the file, ignoring all subsequent ones (the –List switch);
- Search for all matches, even if there are several of them in one line (-AllMatches);
- Search for lines that don’t match the pattern (the –NotMatch parameter is similar to the –v switch of the grep tool);
- In addition to the directly matched line, display several previous and next lines (the -Context argument);
- Select-String allows specifying the encoding of the input file (parameter -Encoding). The following encodings are supported: ASCII, BigEndianUnicode, OEM, Unicode, UTF7, UTF8, UTF8BOM, UTF8NoBOM, UTF32.
For example, use the following command to find a list of open ports on your computer (with the Listening status):
netstat -na | Select-String "LISTENING"
If the previous pipe command returns objects rather than text, use the Out-String –Stream command before passing them to Select-String:
Get-Service | Out-String -Stream | Select-String "Running"
You can use the regular expressions (RegEx) in the Select-String cmdlet. For example, the following command will find all files or lines containing the word “Error” in the specified folder:
Get-ChildItem -Path C:\PS | Select-String -Pattern 'Error'
If you need to check all sub-folders, use the -Recurse parameter:
Get-ChildItem "C:\PS\" -Filter *.log -Recurse | Select-String "Failed"|
To display the names of all found files and matching line numbers:
Get-ChildItem "C:\PS\" -Filter *.log -Recurse | Select-String "Failed"| Select Filename, LineNumber, Line, Path | Format-Table
You can copy all files with matches to the specified directory:
Get-ChildItem C:\logs\ -Filter *.log -Recurse | Select-String "Failed"| Copy-Item -Destination C:\Errors
As you can see, the Select-String cmdlet allows you to process string data. Use the Where-Object cmdlet if you need to grep objects (PowerShell Where-object filter).
Note. Check our guide on how to write Output to PowerShell console.
For example, you want to find all processes that use more than 300 MB of RAM:
Get-Process | Where-Object { $_.WorkingSet -gt 314572800 }
Let’s look at a more complex scenario when you need to find lines with IP addresses in a text file. In this case, you need to use a regular expression with the Select-String command:
$regexIPAddress = '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b' $regexIPLocalNetwork = '(10|172|192).\d{1,3}\.\d{1,3}\.\d{1,3}\b' Select-String –Path c:\ps\ip_list.txt -Pattern $regexIPAddress Select-String –Path c:\ps\ip_list.txt -Pattern $regexIPLocalNetwork
In this example, the first Select-String command finds all lines with any IP addresses (even invalid ones). The second one selected only local IP addresses from the private address ranges.
Another common scenario where you need to use grep is to search for matches in text files. For example, the following command will search all .log files in the Exchange directory and return lines that contain the CALL pattern:
Get-Content "D:\exchange\logs\*\*.log" | Select-String -Pattern "CALL"
However, the performance of such a command on large text files will be quite slow. If you need to speed up the search for text in files, it is better to use the -Path parameter in Select-String instead of Get-Content. For example:
Select-String -Path "D:\exchange\logs\*\*.log" -Pattern "CALL"
In the Path parameter, you need to specify the path to the directory or file. This PowerShell command will run about 5 times faster than the previous one.
If you want to exclude some files from the search scope, add the -Exclude parameter. For a case-sensitive search, use the CaseSensitive option (by default, Select-String searches are not case sensitive):
Select-String -Path "D:\exchange\logs\*\*.log" -Pattern "CALL" -Exclude "tmp* -CaseSensitive
You can use the SimpleMatch parameter to perform a simple search with a Select-String. In this case, a simple match is searched without using regular expressions.
For example, the following command will return the entire string if there is at least one match in the object being checked:
$str = "Learn PowerShell" Select-String -InputObject $str -SimpleMatch "shell","grep"
If you grep a file or string with a different encoding, then you can add the additional -Encoding key. It can take the following values:
- ASCII;
- BigEndianUnicode;
- OEM;
- Unicode;
- UTF7;
- UTF8;
- UTF8BOM;
- UTF8NoBOM (used by default);
- UTF32;
- Windows-1251 (in PowerShell Core 6.2+).
1 comment
Thank you very much for the interesting contribution. Maybe you also have an answer to the following question:
How can I search for an expression in one or more files with a command line and output this line as well as the two preceding and the three following with line number. (like with grep -B 2 -A3)
I would be very happy about a solution ;-)
Best regards