Finding things
which
Show which executable file in PATH would run for a command name.
which [-as] COMMAND...
which searches the directories in $PATH, in order, and prints the full path of the first
executable file with the given name: the program that would run if you typed that name. It is
the quick answer to "which python is this?" or "why does my script get the old version?".
It is an external program and only knows about files. It cannot see shell builtins (cd,
echo), functions or aliases, which the shell checks before searching PATH, so for those
it prints nothing or the wrong answer. In bash, type -a name shows everything the shell
would consider, and in scripts the portable test for "is this command available?" is
command -v name.
On Debian and Ubuntu which is a small shell script from debianutils with two options, -a
and -s. Other systems have other implementations (GNU which, the BSD one, a zsh builtin) with
different options and output, another reason to prefer command -v in scripts.
Examples
Find the program a command runs
which grep
/usr/bin/grep
The first match in $PATH is printed. Exit status 0 means it was found.
Look up several names at once
which python3 nosuchcmd jq
/usr/bin/python3 /usr/bin/jq
Each name found is printed; missing names print nothing. The exit status is 1 because at least one name was not found.
Show every match in PATH with -a
which -a ls
/usr/bin/ls /bin/ls
-a lists all executables with that name, in PATH order; the first is the one that
runs. On Debian with merged /usr, /bin is a symlink to /usr/bin, so the same file
appears under both directories.
Spot a command shadowed earlier in PATH
Setup run before this example
mkdir -p /home/dev/bin
printf '#!/bin/sh\necho "my own ls"\n' > /home/dev/bin/ls
chmod +x /home/dev/bin/lsPATH="$HOME/bin:$PATH"
which -a ls
ls
/home/dev/bin/ls /usr/bin/ls /bin/ls my own ls
A directory earlier in PATH wins. which -a makes the problem visible: ~/bin/ls comes
first, so typing ls runs it instead of the real one.
which cannot see builtins, aliases or functions
greet() { echo hi; }
which cd greet echo; echo "which exit status: $?"
type cd greet echo
/usr/bin/echo
which exit status: 1
cd is a shell builtin
greet is a function
greet ()
{
echo hi
}
echo is a shell builtin which finds nothing for cd or the function, and for echo it reports /usr/bin/echo
although bash would run its builtin. type asks the shell itself and gets all three
right, printing the function's body. Aliases are invisible to which in the same way.
Follow alternatives and symlinks to the real file
which awk
readlink -f "$(which awk)"
/usr/bin/awk /usr/bin/gawk
/usr/bin/awk is a symlink managed by Debian's alternatives system. readlink -f
resolves the chain and shows that awk is gawk here.
Test whether a command exists
if which -s jq; then echo "jq is installed"; fi
if command -v rg >/dev/null; then echo "rg found"; else echo "rg not installed"; fi
jq is installed rg not installed
-s prints nothing and only sets the exit status. It works with Debian's and the BSD
which, but not every version; command -v is the POSIX form and is what scripts should
use.
Common pitfalls
whichignores aliases, functions and builtins, so its answer can differ from what actually runs. Usetype -ain bash.Do not use
whichin portable scripts to check for a program: implementations differ in options, output and even exit status.command -v name >/dev/nullis POSIX.bash remembers where it found a command (
hash). After installing a new version earlier inPATH, the shell may still run the old one even thoughwhichshows the new path. Runhash -r.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
Debian and Ubuntu use the debianutils
which(-a,-s). Red Hat-family systems use GNU which, which can also read aliases with--read-alias. macOS has a BSDwhichthat supports-aand-s. zsh haswhichas a builtin that does report aliases and functions.
Options worth knowing
A selection, described in our own words. For the full list, see which(1) or which --help.
| Option | What it does |
|---|---|
-a | Print every matching executable in PATH, not just the first. |
-s | Print nothing; only set the exit status. |
Related
whereisLocate the binary, source and manual page files for a command in the standard system directories.typeShow how the shell would interpret a name, as an alias, keyword, function, builtin or file on PATH.commandRun a command while skipping functions and aliases of the same name, or check whether a command exists with -v.readlinkPrint where a symbolic link points, or with -f the fully resolved path of any file.- Environment variablesHow export passes variables to child processes, the one-command NAME=value prefix, loading .env files, and why a child cannot change its parent.
- Running scriptsThe four ways to start a script (./script, bash script, PATH, source), what each one changes, and the errors you get when one goes wrong.