Grep is a powerful command-line tool for searching text files for specific patterns. It has become a staple for many developers and system administrators. Select-String is the native PowerShell alternative to grep.
Fear not! PowerShell includes the Select-String cmdlet, which provides functionality similar to the grep utility available on Unix-like systems. In this blog post, we will explore the functionalities of Select-String and how it can be used as a substitute for grep.
The Select-String Cmdlet: Overview
Select-String is a cmdlet in PowerShell that allows you to search for text patterns in files or strings. It provides several features that make it a powerful tool for text searching.
Select-String in Windows PowerShell and PowerShell 7
The Select-String cmdlet is available in both Windows PowerShell 5.1 and PowerShell 7.x. While the core functionality remains the same, in most new PowerShell development and automation projects you should use PowerShell 7 whenever possible.
You can check your current PowerShell version with the command:
$PSVersionTable
PowerShell 7 provides ongoing feature updates, performance improvements, and cross-platform support for Windows, Linux, and macOS. Keep in mind that the examples in this article work in both Windows PowerShell 5.1 and PowerShell 7 unless otherwise noted.
What can this cmdlet do?
Select-String can:
- Search for specific strings or patterns in files.
- Perform case-sensitive or case-insensitive searches.
- Search for all matches or just the first match.
- Search for strings from the pipeline.
- Search for strings using regular expressions.
- Provide context around the matching strings.
Parameters
Select-String has various parameters that can be used to customize the search. Letโs break down some of the common parameters:
- Pattern: Specifies the regular expression pattern or string you want to search for.
- Path: Specifies the file or files to search through. You can use wildcards to specify multiple files.
- AllMatches: Returns all matches found in a file rather than just the first match in each line.
- CaseSensitive: Performs a case-sensitive search.
- Context: Specifies the number of lines of context to include before and after each match.
- Encoding: Specifies the character encoding of the files being searched.
- Exclude: Specifies one or more file patterns to exclude from the search.
- Include: Specifies one or more file patterns to include in the search.
- List: Displays only the files containing a match rather than the matching lines.
- Multiline: Treats the input as a single string with multiple lines.
- When searching multi-line content, Get-Content -Raw can be used to load the entire file as a single string before passing it to Select-String.
- Quiet: Suppresses the output and only returns a Boolean value indicating whether a match was found.
- SimpleMatch: Performs a simple string match instead of using regular expressions.
- NotMatch: Excludes matches that match the specified pattern.
Now, letโs dive into some specific use cases of Select-String.
Finding Strings from Files
One of the most common use cases of Select-String is to search for specific strings in files. You can provide a file path or a wildcard pattern to search multiple files simultaneously.
In this example, I have two CSV files called user_data_01.csv and user_data_02.csv, containing fictitious user data. You can download these sample files from this Gist.
For example, to find the occurrences of the word โoliviaโ in all CSV files within a directory, you can use the following command:
Select-String -Path "*.csv" -Pattern "olivia"
This PowerShell grep equivalent command will display the matching lines, file name, and line number.

Note. Select-String treats the search pattern as a regular expression by default. To perform a literal string search without using regular expressions, you should use the -SimpleMatch parameter. This parameter tells Select-String to treat the search pattern as a plain text string instead of a RegEx expression. Here is an example:
Select-String -Path "*.csv" -Pattern "olivia" -SimpleMatch
Searching Files Recursively
In real-world admin environments, log files, config files, and scripts are often distributed across multiple folders and subfolders. To search recursively, you need to combine Get-ChildItem with Select-String.
For example, you need to find all occurrences of the word “ERROR” in log files under the C:\Logs directory. Use the following command
Get-ChildItem -Path C:\Logs -Filter *.log -Recurse |
Select-String -Pattern "ERROR"
Note that you can improve performance by avoiding unnecessary file processing when using -Filter *.log.
The command mentioned above searches every .log file in the specified directory tree and returns the matching lines, file names, and line numbers.
This method can be simpler when you only need to search files and do not require additional filtering with Get-ChildItem.
Here are the examples:
# Search IIS logs
Get-ChildItem -Path C:\inetpub\logs -Filter *.log -Recurse |
Select-String -Pattern "500"
# Search PowerShell scripts
Get-ChildItem -Path C:\Scripts -Filter *.ps1 -Recurse |
Select-String -Pattern "Invoke-WebRequest"
# Search configuration files
Get-ChildItem -Path C:\Configs -Recurse -File |
Select-String -Pattern "Password"
Note. The -Recurse parameter belongs to Get-ChildItem, not Select-String. This approach works in both Windows PowerShell 5.1 and PowerShell 7.
Performance Considerations
When searching large collections of files, you need to try to limit the search scope as much as possible. You should use file filters, specific paths, and recursive searches only when necessary can significantly improve performance.
For example, the following command searches only .log files:
Get-ChildItem C:\Logs -Filter *.log -Recurse |
Select-String -Pattern "ERROR"
This method is generally faster than searching every file in a directory tree.
You should follow the recommendations below when possible:
- Use `-Filter` with `Get-ChildItem`
- Search specific file types instead of all files
- Limit the search path to relevant folders
- Use recursive searches only when required
Note that these practices become increasingly important when working with large log repositories, script collections, and config file archives.
Finding All Matches
By default, Select-String returns matching lines but does not enumerate every match occurrence within the line. If you want to retrieve all matches, you can specify the -AllMatches switch, which is particularly useful when searching for patterns that may occur multiple times within a line.
This example command returns all matches of the word โoliviaโ in the file.
Select-String -Path "*.csv" -Pattern "olivia" -AllMatches
As you can see, the matches include the first name and part of the email address.

Running a Case-Sensitive Search
By default, Select-String performs a case-insensitive search. However, if you need to perform a case-sensitive search, you can use the -CaseSensitive parameter. For example, to search for the word โoliviaโ in a case-sensitive manner, you can use the following:
Select-String -Path "*.csv" -Pattern "olivia" -AllMatches -CaseSensitive
This PowerShell grep equivalent command will only return the exact matches with the same casing. As you can see below, the search ignored instances of the word โOliviaโ because it does not match the search pattern โoliviaโ.

Finding Strings from the Pipeline Objects
One of the advantages of Select-String is its ability to accept input from the pipeline. You can combine it with other cmdlets to perform more complex operations. But remember that Select-String operates on string representations of objects. What does this mean?
Note that all PowerShell objects inherit the ToString() method from .NET. However, the string representation returned by ToString() is often not useful for searching object properties. In such cases, it is usually better to filter object properties directly with Where-Object.

But you can convert the object to a string before passing it to the Select-String pipeline. You can do so using the Out-String cmdlet before the PowerShell grep equivalent command.
# Convert the output to a single multi-line string object <cmdlet> | Out-String # Convert the output to multiple single-line string objects <cmdlet> | Out-String -Stream
In case you need to search object properties, it is usually more efficient to filter the objects directly instead of converting them to text.
For example, to find services whose name contains “appx“, use the following command:
Get-Service |
Where-Object Name -match 'appx'

In order to search by display name, use the command:
Get-Service |
Where-Object DisplayName -match 'appx'
Filtering object properties is generally faster and more reliable than converting objects to strings and searching the formatted output.
However, Select-String can still be useful when searching formatted text output:
Get-Service |
Out-String -Stream |
Select-String -Pattern 'appx'

The approach mentioned above searches the text representation of the service list rather than the service object properties.
Searching Multi-Line Content with Get-Content -Raw
By default, Get-Content reads a file as an array of strings, where each line is processed separately. This behavior works well for most searches but can make it difficult to search for patterns that span multiple lines.
In order to read the entire file as a single string, you should use the -Raw parameter:
Get-Content .\application.log -Raw |
Select-String -Pattern "Error.*Timeout"
Using -Raw is especially useful when you are working with log files, config files, JSON documents, or other structured text where the data you are searching for may span multiple lines.
For example, to search for a pattern that spans multiple lines, use the following command:
Get-Content .\application.log -Raw |
Select-String -Pattern '(?s)Exception.*StackTrace'
Note that the `(?s)` regular expression option enables Singleline mode, allowing the dot (`.`) character to match newline characters.
Finding Strings with Context
In addition to retrieving matching lines, Select-String also provides the ability to include context around the matching lines. The -Context parameter allows you to specify the number of lines to include before and after the matching line.
For example, this command finds the string matching the email address. The -Context 3 parameter will include three context lines around the matching lines.
Select-String -Path .\*.csv -Pattern "liamstewart@koala.com" -Context 3

If you want to display different numbers of lines before and after the match, like, 1 line before and 2 lines after, you can add another integer value to the parameter.
Select-String -Path .\*.csv -Pattern "liamstewart@koala.com" -Context 1, 2
In this example, the -Context 1,2 parameter included 1 before and 2 after context lines.

This PowerShell grep equivalent command is helpful when reviewing logs for errors. The -Context parameter can provide context (what happened before and after the error) and aid you in troubleshooting.
Searching Log Files for Errors and Events
One of the most common admin uses of Select-String is searching log files for errors, warnings, and other important events. For example, you can search all log files in the current directory for the word “ERROR” with the following command:
Select-String -Path *.log -Pattern "ERROR"
The command returns the matching line, file name, and line number.
You can also search for exceptions in app logs:
Select-String -Path *.log -Pattern "Exception"
Or search for multiple patterns at once:
Select-String -Path *.log -Pattern "ERROR","WARNING","CRITICAL"
Searching log files is one of the most practical uses of Select-String when troubleshooting Windows servers, apps, and services.
Here are other common examples:
# IIS errors Select-String -Path *.log -Pattern "500" # Authentication failures Select-String -Path *.log -Pattern "failed" # PowerShell exceptions Select-String -Path *.log -Pattern "Exception" # DNS-related events Select-String -Path *.log -Pattern "DNS"
The approach mentioned above is useful when searching IIS logs, app logs, exported text reports, and other large collections of log files.
For large log repositories spread across multiple directories, you should combine the techniques shown in this section with the recursive search methods described earlier in Searching Files Recursively.
Searching PowerShell Scripts and Source Code
Select-String is commonly used to search through PowerShell scripts, config files, and source code repositories.
For example, to find all scripts that contain the Invoke-WebRequest cmdlet, use the following command:
Select-String -Path *.ps1 -Pattern "Invoke-WebRequest"
The command above returns the matching file names, line numbers, and matching lines.
In order to search all PowerShell scripts in a directory tree, run the command:
Get-ChildItem -Path C:\Scripts -Filter *.ps1 -Recurse |
Select-String -Pattern "Invoke-WebRequest"
Note that this technique is useful when auditing large script repositories or identifying where a specific command, variable, or function is used.
Here are common code-search cases:
# Find hardcoded passwords
Get-ChildItem -Path C:\Scripts -Filter *.ps1 -Recurse |
Select-String -Pattern "Password="
# Find secrets
Get-ChildItem -Path C:\Scripts -Filter *.ps1 -Recurse |
Select-String -Pattern "Secret"
# Find API keys
Get-ChildItem -Path C:\Scripts -Filter *.ps1 -Recurse |
Select-String -Pattern "ApiKey"
Searching source code with Select-String is particularly useful for script reviews, migration projects, security audits, and troubleshooting automation workflows.
Note. These simple text searches mentioned above are a starting point for security audits, not a comprehensive secret-detection solution. They will miss base64-encoded values, secrets split across multiple lines, or non-standard variable naming. For production secret scanning, you should consider dedicated tools (such as git-secrets, TruffleHog, or GitHub secret scanning).
Finding Strings with RegEx Patterns
Select-String also has a PowerShell grep equivalent of searching with regular expressions, which allows for more advanced pattern matching. Here are a few examples of using regular expressions.
Email Address
To search for email addresses within a file, you can use the following pattern:
$emailAddressPattern = '\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\b'
Select-String -Path .\*.csv -Pattern $emailAddressPattern 
Social Security Number
Our sample CSV files also contain the Social Security Number for each fictitious user. To search for Social Security Numbers (SSNs), you can use the following pattern:
$ssnPattern = '\b\d{3}-\d{2}-\d{4}\b'
Select-String -Path .\*.csv -Pattern $ssnPattern 
Note. Searching for SSN patterns is commonly used in data discovery and compliance audits (e.g., identifying PII before migrating data, GDPR/CCPA compliance scans). You should always ensure you have authorization before scanning files for sensitive personal data.
IP Address
To search for IP addresses, you can use the following pattern:
$ipPattern = '\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b'
Select-String -Path .\*.csv -Pattern $ipPattern -AllMatches 
As you can see, the PowerShell grep equivalent Select-String command matched all instances of IP addresses. What if you want to find private and public IP addresses separately?
Hereโs the RegEx pattern for valid private IP addresses.
$privateIpPattern = '\b(?:10|172\.(?:1[6-9]|2\d|3[01])|192\.168)\.\d{1,3}\.\d{1,3}\b'
Select-String -Path .\*.csv -Pattern $privateIpPattern -AllMatches 
Hereโs the RegEx pattern for valid public IP addresses.
$publicIpPattern = '\b(?!(?:10|172\.(?:1[6-9]|2\d|3[01])|192\.168)\.\d{1,3}\.\d{1,3}\b)\b(?:(?:\d{1,3}\.){3}\d{1,3})\b'
Select-String -Path .\*.csv -Pattern $publicIpPattern -AllMatches 
Conclusion
While Windows may not have the native grep command, it has an excellent PowerShell grep equivalent Select-String cmdlet.
With its various parameters and features, Select-String allows you to perform text searches in files or strings, handle case-sensitive searches, find all matches, search using regular expressions, and even provide context around the matching lines.
So, next time you find yourself in a Windows environment and need to search for specific strings, try Select-String!
What is Select-String in PowerShell?
Select-String is a PowerShell cmdlet used to search for text patterns in files or strings. It is the built-in alternative to the Unix/Linux grep command and supports both simple text searches and regular expressions.
Is Select-String available in all PowerShell versions?
Yes. Select-String is available in both Windows PowerShell 5.1 and PowerShell 7.x.
However, PowerShell 7 is recommended for new projects due to performance improvements and cross-platform support.
What is Select-String best used for?
It is best used for:
- Fast text searching across files
- Log analysis and troubleshooting
- Script and code auditing
- Pattern matching with regex in automation tasks
What is the main limitation of Select-String?
It works on text representations, not structured object properties. For object filtering, Where-Object is usually more efficient and reliable.

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
Any way to not make it print the filename and line if found the string on?