Skip to content
shellmap

command-vPOSIX way to test whether a command exists and where it resolves across all 5 shells

Equivalents in every shell

Bashunix
command -v python3

POSIX-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 python3

POSIX; works identically to bash. Zsh prefers a builtin over an external when both exist.

Fishunix
command -v python3

Fish supports `command -v` since 2.7. Older fish versions need `type -q` instead.

PowerShellwindows
Get-Command python3 -ErrorAction SilentlyContinue

No `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; fi
Fish
if command -v jq >/dev/null; echo found; else; echo missing; end
PowerShell
if (Get-Command jq -ErrorAction SilentlyContinue) { "found" } else { "missing" }
cmd.exe
where /Q jq && echo found || echo missing

Bypass 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).Source

Gotchas

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

Related commands