command-v — POSIX way to test whether a command exists and where it resolves across all 5 shells
Equivalents in every shell
Bashunix
command -v python3POSIX-portable. Prints a path for external commands; prints the name for builtins/functions/aliases. Exit status non-zero if not found — making it the canonical `if command -v X` script idiom.
Zshunix
command -v python3POSIX; works identically to bash. Zsh prefers a builtin over an external when both exist.
Fishunix
command -v python3Fish supports `command -v` since 2.7. Older fish versions need `type -q` instead.
PowerShellwindows
Get-Command python3 -ErrorAction SilentlyContinueNo `command -v`. The idiomatic existence check is `Get-Command <name> -ErrorAction SilentlyContinue` (returns `$null` when missing instead of throwing).
cmd.exewindows
where /Q python3`/Q` (quiet) sets `%ERRORLEVEL%` to 0 if found, 1 if not — no output. The closest cmd equivalent to a POSIX exit-status check.
Worked examples
Branch on whether a command is available
Bash
if command -v jq >/dev/null; then echo found; else echo missing; fiFish
if command -v jq >/dev/null; echo found; else; echo missing; endPowerShell
if (Get-Command jq -ErrorAction SilentlyContinue) { "found" } else { "missing" }cmd.exe
where /Q jq && echo found || echo missingBypass shell aliases and call the real binary
Bash
command grep "TODO" .Zsh
command grep "TODO" .PowerShell
& (Get-Command -CommandType Application grep).Source "TODO" .Capture the resolved path in a variable
Bash
JQ=$(command -v jq)Fish
set JQ (command -v jq)PowerShell
$JQ = (Get-Command jq -ErrorAction SilentlyContinue).SourceGotchas
- `command -v` is the POSIX-blessed existence check. Prefer it over `which` in scripts you want to run on Alpine, BusyBox, or any minimal system where `which` may not be installed.
- For builtins, `command -v` prints the *name* (`cd`), not a path. Scripts that do `path=$(command -v cd); ls $path` break because `cd` has no filesystem path.
- `command` (without `-v`) bypasses functions and aliases and runs the underlying binary/builtin. Useful when a function shadows a name and you need the original — e.g. `command grep` when `grep` is aliased.
- PowerShell's `Get-Command` writes an *error* by default when a command is missing — always pair with `-ErrorAction SilentlyContinue` (or `$?` check) in scripts, or you'll see red noise on stderr.
- Cmd's `where /Q` is the only quiet existence-check built into Windows; without `/Q` you get printed paths even on success, which corrupts otherwise-silent script output.
WSL & PowerShell Core notes
pwshpwsh has no `command -v` builtin on any platform — `command` itself does not exist as a cmdlet. The portable existence-check idiom is `if (Get-Command jq -ErrorAction SilentlyContinue) { ... }`, which returns `$null` when the command is missing instead of throwing. `Get-Command` returns a `CommandInfo` object (with `.Source` for the resolved path) — richer than the bare path or name `command -v` prints. For polyglot bash + pwsh scripts (rare), branch on `$IsCoreCLR` / `$PSVersionTable` rather than trying to share the same line.
WSLInside WSL bash, `command -v` is the POSIX builtin and works identically to native Linux. WSL's interop automatically appends Windows-side PATH directories to the WSL `$PATH` (controlled by `interop.appendWindowsPath` in `/etc/wsl.conf`, default true), so `command -v notepad.exe` resolves to `/mnt/c/Windows/system32/notepad.exe` and `command -v code` may resolve to the Windows-side VS Code launcher. Set `appendWindowsPath=false` if you want strict Linux-only PATH semantics for hermetic build scripts.