which / type / command
| Since: | which | All Linux |
|---|---|---|
| macOS(2001 Cheetah) | ||
| Bash 1.0(1989) | ||
| type / command | All Linux | |
| macOS(2001 Cheetah) | ||
| Bash 1.0(1989) |
These are commands for finding the location or type of a command. which, type, and command -v are all used to answer "where is this command and what is it?", but they differ in behavior and intended use. Understanding the distinction is important for writing portable shell scripts.
Syntax
which displays the full path to an executable by searching the PATH environment variable.
which command_name
type shows the kind of command — builtin, alias, function, or external file. It is a builtin of bash and zsh.
type command_name type -a command_name
command -v is a POSIX-compliant way to check whether a command exists. It is commonly used when portability is required in shell scripts.
command -v command_name
Command Comparison
| Command | Scope | Shows aliases | Shows builtins | POSIX compliant |
|---|---|---|---|---|
| which | External commands (PATH search) | Environment-dependent | No | No |
| type | All types | Yes | Yes | No (bash/zsh builtin) |
| command -v | All types | Yes | Yes | Yes |
Sample Code
Use which to find the full path to an executable.
which bash /bin/bash
Run the following command:
which python3 /usr/bin/python3
If the command is not found, nothing is output or an error message appears.
which myapp which: no myapp in (/usr/local/bin:/usr/bin:/bin) echo $? 1
Use type to identify what kind of command something is — builtin, alias, or external file.
type cd cd is a shell builtin type ls ls is aliased to `ls --color=auto' type bash bash is /bin/bash type grep grep is /usr/bin/grep
The -a option lists all matches for a given name — useful when both an alias and an external binary share the same name.
type -a ls ls is aliased to `ls --color=auto' ls is /usr/bin/ls ls is /bin/ls
Use command -v to check whether a command exists. Because it is POSIX-compliant, it works in scripts starting with #!/bin/sh.
command -v git /usr/bin/git command -v nonexistent
When a command does not exist, nothing is output and the exit status is 1.
check_dependencies.sh
#!/bin/sh
# Check for required commands before launching the app
for cmd in curl jq git; do
if ! command -v "$cmd" > /dev/null 2>&1; then
echo "Error: '$cmd' not found. Please install it." >&2
exit 1
fi
done
echo "All commands verified. Launching the app."
APP_LOG="$HOME/app_startup.log"
echo "$(date): App launched" >> "$APP_LOG"
Branch on command availability — use python3 if available, fall back to python otherwise.
python_check.sh
#!/bin/sh
# Determine the Python command to process data
if command -v python3 > /dev/null 2>&1; then
PYTHON=python3
elif command -v python > /dev/null 2>&1; then
PYTHON=python
else
echo "Python not found." >&2
exit 1
fi
$PYTHON process_data.py
Overview
which searches PATH for an external executable. It may return nothing for shell builtins or aliases. For example, which ls returns /bin/ls, but if ls is aliased, which may not show the alias — the exact behavior depends on the shell and environment.
type is a builtin in bash and zsh that can identify aliases, functions, builtins, and external files. Because it is not defined by POSIX, it may not be available in #!/bin/sh scripts depending on the system.
command -v is defined by POSIX and is the most portable of the three options. It outputs the path or command name if the command exists, and returns exit status 1 if it does not. command -v is widely used for existence checks in shell scripts.
Common Mistakes
Common Mistake 1: which does not show aliases
which only searches for external commands on PATH. Aliases and functions are not shown, which can lead to a mismatch between "the path which returned" and "what actually runs when you type the command".
alias ls='ls --color=auto' which ls /bin/ls type ls ls is aliased to `ls --color=auto'
which ls ignores the alias and returns /bin/ls. But typing ls in the terminal actually runs ls --color=auto. To see what a command really does, type is a more accurate option.
Common Mistake 2: Trusting which's exit status unconditionally
On some systems, which may return exit status 0 even for commands that do not exist. Using which for existence checks in scripts can cause behavior that varies by environment.
The example below uses which for an existence check. Because the exit status behavior varies across environments, the result is not reliable.
#!/bin/sh
if which check_inventory.sh > /dev/null 2>&1; then
echo "Command found"
fi
The same check written with the POSIX-compliant command -v. Every POSIX-compliant shell returns the same exit status.
#!/bin/sh
if command -v check_inventory.sh > /dev/null 2>&1; then
echo "Command found"
fi
For command existence checks in shell scripts, command -v behaves consistently across POSIX-compliant shells.
If you find any errors or copyright issues, please contact us.