Skip to content
shellmap

select-stringPowerShell's pattern-search cmdlet — the grep equivalent across all 5 shells

Equivalents in every shell

Bashunix
grep "pattern" file.txt

Add `-r` to recurse, `-i` for case-insensitive, `-E` for extended regex.

Zshunix
grep "pattern" file.txt
Fishunix
grep "pattern" file.txt
PowerShellwindows
Select-String -Pattern "pattern" -Path file.txt

Aliased 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" *.log

Print 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 Path
cmd.exe
findstr /M "pattern" *.txt

Match any of several alternatives in one pass

Bash
grep -E "error|warn|fatal" app.log
PowerShell
Select-String -Pattern "error","warn","fatal" -Path app.log
cmd.exe
findstr "error warn fatal" app.log

Gotchas

  • `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

Related commands