which — quick reference
Lookup
Resolve command names against PATH — the same ordered search the shell uses when you type a bare name.
| When to use | Command |
|---|---|
| Print the first executable found for a command | which grep |
| List every matching executable in PATH (not only the first) | which -a grep |
| Resolve several commands in one invocation | which ls bash sudo |
Show the path to which itself |
which which |
Shell integration
| When to use | Command |
|---|---|
| POSIX-friendly check in bash scripts (preferred over which) | command -v grep |
| Show alias, function, or builtin resolution | type grep |
| Print your PATH colon-separated list | echo "$PATH" |
Notes
which does not read man which --help on Debian — only -a and -s are supported. It ignores shell aliases unless you run it from a context where aliases are expanded.
which — command syntax
Usage from /usr/bin/which on Ubuntu 25.04 (debianutils):
which [-as] args-a lists all matches in PATH order. -s returns only the exit status (quiet). There is no long --help flag on this build.
which — command examples
Essential Resolve one command
When a script fails with "command not found", which shows the binary the shell would execute if the name is on PATH.
which grepSample output:
/usr/bin/grepIf nothing is found, which prints nothing and exits with status 1.
Essential All PATH matches (-a)
Some distributions install the same command under /usr/bin and /bin. Default which stops at the first hit; -a lists every match.
which -a grepSample output:
/usr/bin/grep
/bin/grepUse this when debugging unexpected versions — the first path wins for interactive PATH order.
Common Several commands at once
Pass multiple names to avoid repeated invocations in setup scripts.
which ls bash sudoSample output:
/usr/bin/ls
/usr/bin/bash
/usr/bin/sudoEach line corresponds to one argument in order.
Common Missing command — exit status
When the name is not executable on PATH, which is silent on stdout. Check $? in scripts.
which nonexistent_cmd_xyz_42
echo "exit code: $?"Sample output:
exit code: 1Do not rely on parsing empty output alone in strict scripts — test the exit code.
Advanced Compare with type and command -v
which is an external program and may not see bash aliases or functions. type and command -v run inside the shell and are safer in bash scripts.
type which
command -v grep
which grepSample output:
which is hashed (/usr/bin/which)
/usr/bin/grep
/usr/bin/grepFor aliases, type ls may show alias ls='…' while which ls still prints /usr/bin/ls if an alias is not exported to non-interactive paths.
Advanced Inspect PATH order
which only searches directories listed in PATH. Inspect the variable when results surprise you.
echo "$PATH" | tr ':' '\n' | head -8Sample output (order matters — first directories win):
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/gamesPut custom prefixes early when you need your build to shadow system binaries.
which — when to use / when not
| Use which when | Use something else when |
|---|---|
| You want a quick PATH lookup at the terminal | You write bash scripts → prefer command -v |
You need every duplicate binary (-a) |
You need man pages and source paths → whereis or find |
| You are checking after package install | You search the whole disk by name → locate or find |
| You debug "wrong version" of a CLI tool | You need file metadata → ls -l $(command -v tool) |
| You verify cron's minimal PATH | Export PATH in the crontab or script — which only reflects current PATH |
which vs command -v
| which (debianutils) | command -v (bash builtin) | |
|---|---|---|
| Runs as | External executable | Shell builtin |
| Sees aliases/functions | No | Yes |
| POSIX scripts | Discouraged | Recommended |
| Lists all matches | -a |
No (first resolution) |
| Speed in loops | Spawns process | Builtin — faster |
Portable scripts should use command -v name and test $?.
Related commands
| Command | One line |
|---|---|
whereis |
Binary, source, and man paths |
type |
Bash reserved word, function, alias, or file |
Browse the full index in our Linux commands reference.
which — interview corner
What does the which command do?
which searches directories in the PATH environment variable, in order, for an executable file matching each argument. It prints the first path found, or with -a, every match.
It does not search the entire filesystem — only PATH entries.
A strong answer is:
"which walks PATH and prints the executable that would run for a name. -a shows every match; exit 1 if none."
Why do bash style guides prefer command -v over which?
which is an external program. It does not understand shell aliases or functions and may not exist in minimal containers. command -v is a POSIX builtin that resolves the same way the shell will execute the name.
command -v gitA strong answer is:
"command -v is POSIX and builtin — it sees aliases and functions. which is an external PATH-only lookup; I use command -v in scripts."
When would you use which -a?
When multiple copies of a binary exist — for example /usr/bin/python3 and /usr/local/bin/python3. The first PATH entry wins for execution; -a reveals hidden alternates.
A strong answer is:
"which -a lists every PATH match — I use it when debugging wrong Python or Java versions shadowed earlier on PATH."
What exit code does which return when a command is missing?
It returns 1 when no executable is found and 0 when at least one argument resolves. Combine with $? in scripts instead of parsing empty output.
A strong answer is:
"Missing name → exit 1, found → 0. I test $? after command -v or which in scripts."
What does which not tell you?
It does not report man pages, libraries, or config paths (whereis does). It does not confirm the file is the right architecture, only that it is executable and named on PATH. It also ignores shell builtins unless you use type.
A strong answer is:
"which only resolves PATH executables — not man paths, not aliases, not whether the binary is correct for my arch. For scripts I use command -v; for broader search, whereis or locate."
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
which prints nothing |
Name not on PATH or not executable | Install package; fix PATH; use full path |
| Wrong version runs | Earlier PATH directory shadows later one | which -a cmd; reorder PATH or use absolute path |
which differs from what runs |
Alias or function in interactive shell | Run type cmd |
| Cron cannot find command | Minimal cron PATH | Set PATH= at top of crontab or use full path |
Illegal option -- |
GNU which flags on debianutils build | Use only -a and -s; see man page |
| Snap or flatpak binary missing | Special paths not in script PATH | Use distro package or export snap bin path |
