The PowerShell Select-String cmdlet finds text inside files — the same job grep does on Linux/macOS and findstr does in classic CMD. When you are hunting for an error code in logs, checking whether a config key exists, or scanning a repo for a TODO, it is faster than opening every file by hand.
For the official reference, see Microsoft Learn’s Select-String.
Want to practice PowerShell in a live browser terminal (no install)? Try the free interactive lessons on CMD Master — PowerShell and command-line training.
What does Select-String do?
Select-String -Path .\notes.txt -Pattern "TODO"
That prints every line in notes.txt that contains TODO, plus the file name and line number. Matches are case-insensitive by default on Windows PowerShell 5.1; add -CaseSensitive when case matters.
Search one file or many
Point -Path at a single file, a wildcard, or a list:
Select-String -Path .\app.log -Pattern "ERROR"
Select-String -Path .\*.log -Pattern "timeout"
Select-String -Path .\config.json,.\settings.json -Pattern "apiKey"
Preview what you will search with Get-ChildItem first when the wildcard is broad:
Get-ChildItem .\*.log
Select-String -Path .\*.log -Pattern "Exception"
Recurse into folders: -Recurse
To walk a directory tree, combine a path with -Recurse (or pipe files in):
Select-String -Path .\logs\*.log -Pattern "FATAL" -Recurse
Or pipe from Get-ChildItem for tighter filters:
Get-ChildItem .\src -Filter *.ps1 -Recurse |
Select-String -Pattern "Write-Host"
Piping is often clearer when you want to exclude folders, filter by extension, or skip huge binary files.
Patterns: simple text and regex
-Pattern accepts a string or a regular expression:
# literal-ish search (still regex — escape special characters)
Select-String -Path .\readme.md -Pattern "C:\\Windows"
# regex: lines that look like IPv4 addresses
Select-String -Path .\access.log -Pattern '\d{1,3}(\.\d{1,3}){3}'
To treat the pattern as plain text (no regex), use -SimpleMatch:
Select-String -Path .\notes.txt -Pattern "C:\temp\file[1].txt" -SimpleMatch
Show surrounding lines: -Context
-Context shows lines before and after each match — perfect for log forensics:
# 2 lines before, 3 lines after
Select-String -Path .\app.log -Pattern "NullReference" -Context 2,3
You can also pass a single number for the same count on both sides: -Context 2.
List only matching files
Sometimes you care which files contain a string, not every hit:
Select-String -Path .\*.config -Pattern "ConnectionString" -List
-List stops after the first match in each file, which is faster on large trees.
Case, invert, and quiet checks
# case-sensitive
Select-String -Path .\code.ps1 -Pattern "Error" -CaseSensitive
# lines that do NOT match
Select-String -Path .\hosts.txt -Pattern "^#" -NotMatch
In scripts, test whether anything matched with the boolean result of a capture:
$hits = Select-String -Path .\app.log -Pattern "FATAL" -Quiet
if ($hits) {
Write-Host "Found FATAL entries — investigate."
}
-Quiet returns $true / $false instead of match objects.
Select-String vs findstr vs Get-Content
| Tool | Best for |
|---|---|
Select-String |
PowerShell pipelines, regex, recursion, rich match objects |
findstr |
Quick CMD one-liners without loading PowerShell |
Get-Content + Where-Object
|
When you already have content in memory and need custom filters |
Prefer Select-String when you are already in PowerShell. Prefer findstr only for tiny CMD scripts that must stay .bat-only.
Safe habits
-
Narrow the path before a recursive search — start with
Get-ChildItem, then pipe. - Prefer
-SimpleMatchwhen the pattern includes brackets, dots, or backslashes you did not mean as regex. - Use
-Contexton production logs so you see the failure, not just the keyword. - Avoid searching huge binary folders (
node_modules,.git) unless you filter them out.
Practice it live
Open a free PowerShell lesson on CMD Master’s interactive CLI platform and try Select-String in a real terminal in your browser — no VM, no install.
Quick cheat sheet
Select-String -Path .\file.txt -Pattern "text"
Select-String -Path .\*.log -Pattern "ERROR" -Recurse
Select-String -Path .\app.log -Pattern "FAIL" -Context 2,2
Select-String -Path .\*.ps1 -Pattern "TODO" -List
Select-String -Path .\data.csv -Pattern "id,name" -SimpleMatch
Once this clicks, pair it with Get-ChildItem for discovery and Get-Content when you need the full file after a hit. That trio covers most day-to-day text hunting on Windows.
Top comments (0)