select-string — PowerShell's pattern-search cmdlet — the grep equivalent across all 5 shells
Equivalents in every shell
Bashunix
grep "pattern" file.txtAdd `-r` to recurse, `-i` for case-insensitive, `-E` for extended regex.
Zshunix
grep "pattern" file.txtFishunix
grep "pattern" file.txtPowerShellwindows
Select-String -Pattern "pattern" -Path file.txtAliased as `sls`. Emits `MatchInfo` objects with `.Line`, `.LineNumber`, `.Path`, `.Pattern`.
cmd.exewindows
findstr "pattern" file.txt`/I` case-insensitive, `/S` recurse, `/N` show line numbers, `/V` invert match.
Worked examples
Recursively scan every .log file for the word ERROR
Bash
grep -r --include="*.log" "ERROR" .PowerShell
Get-ChildItem -Recurse -Filter *.log | Select-String -Pattern "ERROR"cmd.exe
findstr /S "ERROR" *.logPrint only the file paths that contain a match (not the matching lines)
Bash
grep -lr "pattern" .PowerShell
Select-String -Pattern "pattern" -Path *.txt | Select-Object -Unique Pathcmd.exe
findstr /M "pattern" *.txtMatch any of several alternatives in one pass
Bash
grep -E "error|warn|fatal" app.logPowerShell
Select-String -Pattern "error","warn","fatal" -Path app.logcmd.exe
findstr "error warn fatal" app.logGotchas
- `Select-String` emits `MatchInfo` objects, not plain text — pipe to `ForEach-Object { $_.Line }` to get a string stream that downstream tools (sort, ConvertTo-Csv) treat as lines.
- There is no `-Recurse` switch on `Select-String` — chain `Get-ChildItem -Recurse` and pipe its files in, the way `grep -r .` does the walk in one step.
- Both `Select-String` and `grep` treat the pattern as a regex by default; pass `-SimpleMatch` in PowerShell (or `-F` / `fgrep` in grep) for literal-string matching.
- cmd's `findstr` looks like a grep clone but its regex is severely limited — no `\d`, no `\w`, no lookarounds, no `|` alternation. Space-separated tokens are OR'd unless wrapped in `/C:"..."`.
- Some Unix distros ship `ripgrep` (`rg`) — same intent, much faster — but it is a separate install. `Select-String` is built into every Windows 10+ install.
WSL & PowerShell Core notes
pwsh`Select-String` is part of `Microsoft.PowerShell.Utility` and ships with every pwsh 7+ install on Windows, Linux, and macOS — fully cross-platform. The alias `sls` is also universal. Output is `MatchInfo` objects with structured properties (`.Line`, `.LineNumber`, `.Path`, `.Pattern`); for plain-text output consumable by Unix downstream tools (sort, uniq, awk), pipe through `ForEach-Object { $_.Line }`. Regex flavour is .NET — broadly POSIX-ERE-compatible plus lookarounds, named captures, and `\d`/`\w` shorthand classes (richer than `grep -E`, comparable to `grep -P`).
WSLInside WSL bash, `Select-String` is NOT available by default — it lives in pwsh, which is not pre-installed in any standard WSL distro. To use it from WSL: either invoke Windows-side pwsh via interop (`pwsh.exe -c "Select-String -Pattern ERROR -Path *.log"`), or install pwsh inside the WSL distro (`apt install powershell` after adding Microsoft's apt repo). Most WSL users reach for `grep` or `rg` instead. The reverse direction works fine: Windows-side pwsh can search WSL files via the UNC mount, `Select-String -Path \\wsl$\Ubuntu\home\me\*.log -Pattern ERROR`.
Common tasks using select-string
- Extract a substring by regex
Pull a substring out of a string or a stream of input using a regex — for parsing log lines, extracting an ID from a URL, scraping a version number, or tokenizing a config.
- Extract email addresses from text
Pull every email address out of a log file or block of text.
- Grep recursively with context lines
Search a directory tree for a pattern and print N lines of surrounding context for each match — for code archaeology, log spelunking, or config-file forensics.
- Pipe command output to grep
Filter the stdout of one command through a pattern matcher and print only matching lines.