Shell builtins · bash builtin
command
Run a command while skipping functions and aliases of the same name, or check whether a command exists with -v.
command [-pVv] COMMAND [ARGUMENT...]
command NAME args runs NAME as a builtin or a program from PATH, ignoring any shell
function or alias called NAME. Its main everyday use is inside a wrapper function that has
the same name as the command it wraps: without command, the function would call itself
forever.
Its second job is detection. command -v NAME prints how NAME would be found (a path for
programs, just the name for builtins and functions, the definition for aliases) and returns
non-zero when nothing matches. It is the POSIX way to ask "is this installed?", portable to
dash and every other sh, unlike which, whose behavior and exit status differ between
systems.
command -V gives a human-readable description like type. command -p searches a
default PATH that is guaranteed to find the standard utilities, useful when a script cannot
trust the caller's PATH.
Examples
Check whether a program is installed
for tool in jq curl kubectl; do
if command -v "$tool" >/dev/null 2>&1; then
echo "$tool: found at $(command -v "$tool")"
else
echo "$tool: not installed"
fi
done
jq: found at /usr/bin/jq curl: found at /usr/bin/curl kubectl: not installed
command -v prints the path and returns 0 when the program exists, and prints nothing
and returns 1 when it does not. Redirecting its output keeps the check quiet.
What -v prints for different kinds of names
alias ll='ls -l'
greet() { echo hi; }
command -v grep cd greet ll if
/usr/bin/grep cd greet if
A program gives its full path, a builtin, function or keyword just its name. The alias
ll prints nothing, because this non-interactive shell does not expand aliases; in a
terminal it would print alias ll='ls -l'.
The exit status reflects missing names
command -v kubectl
(no output)
No output and status 1. In a script, command -v kubectl >/dev/null || { echo "kubectl
required" >&2; exit 1; } is the usual guard.
Wrap a command in a function of the same name
grep() { command grep --color=never -n "$@"; }
grep TODO notes.txt src/app.py
notes.txt:5:- TODO: write the deploy script src/app.py:11: # TODO: read the port from the environment
Inside the function, command grep calls the real program instead of the function
itself, so the wrapper adds -n to every call. Without command this function would
recurse until bash runs out of stack.
Bypass a function or alias for one call
ls() { echo "(ls is overridden)"; }
ls scripts
command ls scripts
(ls is overridden) backup.sh greet.sh
The function wins over the program in normal lookup; command ls skips functions and
aliases and runs /usr/bin/ls.
Describe a name with -V
command -V ls cd
ls is /usr/bin/ls cd is a shell builtin
-V prints the same wording as type. Use it in the terminal; parse -v in scripts.
Use a safe default PATH with -p
PATH=/nowhere
ls scripts
command -p ls scripts
/bin/bash: line 2: ls: command not found backup.sh greet.sh
With a broken PATH, ls cannot be found. command -p uses the system's default search
path instead and finds it. Handy at the top of scripts run by cron or other tools with a
minimal environment.
Keep a failing special builtin from exiting a POSIX shell
command . ./missing.sh
echo "still running, status $?"
. ./missing.sh
echo "never reached"
/bin/sh: 1: .: cannot open ./missing.sh: No such file still running, status 2 /bin/sh: 3: .: cannot open ./missing.sh: No such file
In POSIX sh, an error in a special builtin such as ., set or export ends a
non-interactive shell. Prefixing it with command turns it into an ordinary failure that
the script can handle, which is what happens on the first line.
Common pitfalls
Using
whichin scripts to test for a program: its output and exit codes vary across systems and some versions print "no X in ..." to stdout.command -v X >/dev/nullis portable.Forgetting
commandinside a same-named wrapper function:ls() { ls -F "$@"; }calls itself endlessly and crashes the shell.command -vsucceeds for functions and builtins too, so it says a name can run, not that a file exists. Usetype -Pin bash if you need the path to a binary.
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).
command,-v,-Vand-pare POSIX and behave the same in bash, dash, zsh and ksh, on Linux and macOS alike. The exact wording of-Vdiffers between shells.
Options worth knowing
A selection, described in our own words. For the full list, see bash(1), SHELL BUILTIN COMMANDS.
| Option | What it does |
|---|---|
-v | Print the path or name that would be used for the command; status 1 if not found. |
-V | Print a human-readable description of how the name would be interpreted. |
-p | Search a default PATH that finds all standard utilities. |
Related
typeShow how the shell would interpret a name, as an alias, keyword, function, builtin or file on PATH.whichShow which executable file in PATH would run for a command name.whereisLocate the binary, source and manual page files for a command in the standard system directories.aliasDefine a short name that the shell replaces with a longer command line, or list the aliases already defined.execReplace the shell with another program, or, with only redirections, change where the shell's own input and output go.- FunctionsDefining and calling bash functions, arguments, local variables, return status versus output, namerefs, and sourcing a function library.
- 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.
- Exit codesWhat exit statuses mean, how $? works, the reserved values 126, 127 and 128+N, PIPESTATUS, and how to choose codes for your own scripts.