which is non-standard; use builtin command -v instead

`which` is an external command with quirks across distros. `command -v` is the POSIX, builtin way to find a command.

Problem

`which` isn't in POSIX. Different implementations disagree on shell aliases, builtins, and exit codes. Some don't exist by default on minimal containers (Alpine ships without it). `command -v` is a Bash/POSIX builtin that resolves to the same answer the shell would use, without forking.

Bad

if which kubectl >/dev/null; then ...

Good

if command -v kubectl >/dev/null; then ...

Explanation

`command -v` prints the resolved path (or alias/function definition) and exits 0 on success, 1 on failure. It works the same way on every POSIX shell.

When It Matters

which is an external program whose behaviour, exit status, and output format differ between distributions — and Debian removed it from the default install in 2022, so scripts relying on it now fail with "which: command not found" on fresh containers. command -v is a shell builtin specified by POSIX and always present. which also only finds executables in PATH, so it reports failure for shell builtins, functions, and aliases that would in fact run successfully.

Second Example

Note

command -v prints the resolved path for external programs and the name itself for builtins and functions, so it answers "can I run this?" rather than "is there a file for it?".

Exceptions

If you specifically need the filesystem path of an external binary and want to exclude functions and builtins, "type -P name" in Bash does that precisely. which is still acceptable in an interactive shell where you are reading the answer yourself; the warning is about scripts.

Faq

Q

Is command -v POSIX?

A

Yes, it is part of the POSIX specification for the shell and works in sh, dash, ash, ksh, zsh, and bash.

Q

What is the difference between command -v, type, and hash?

A

command -v reports how a name would be resolved, type is a more verbose Bash builtin with the same job, and hash manages the shell’s lookup cache rather than answering existence questions.

Q

Why redirect the output?

A

command -v prints the resolution to stdout. In a check you only want the exit status, so send the output to /dev/null.