The which & type command in Linux
When several versions of a tool coexist (system python, pyenv python, a venv), which prints the one your PATH resolves to. type goes further: it reveals whether a name is an alias, a shell function, a built-in or a file — the truth behind "why does this command behave differently for me?".
How which & type works
which is an outsider: a separate program that walks PATH looking for an executable file with the given name, reporting the first hit. It reproduces the shell's file search — and only that. The shell itself resolves names through a richer sequence first: aliases, functions, builtins, then a cached hash table of previously found commands, and only then PATH.
type is the insider — a builtin with access to all those tables — which is why its answer is the truth about what will actually run. The hash table adds one classic wrinkle: after installing a new version of a tool elsewhere on PATH, a long-lived shell may keep executing the cached old path until "hash -r" clears it. When which, type and reality disagree, the cache is usually the missing suspect.
Syntax
which COMMAND | type [-a] COMMAND Common options
| Option | What it does |
|---|---|
which cmd | The path of the file that would execute. |
type cmd | What KIND of thing the name is (alias/function/builtin/file). |
type -a cmd | Every match on PATH, in resolution order. |
command -v cmd | The POSIX, script-safe spelling. |
How to use which & type: examples
$ which python3 Exactly which interpreter runs — the first question of every environment mixup.
$ type ll "ll is aliased to ls -lah" — unmask the shortcut.
$ type -a python All pythons on PATH in order: the shadowing map.
$ command -v docker >/dev/null || echo "docker not installed" The portable existence check for scripts.
Real-world use cases for which & type
The version-mixup exorcism
Team member "has the new node but old runs": type -a node reveals three installs and their order; which shows the winner; a PATH reorder in .bashrc ends the séance. Ninety seconds, recurring ticket closed.
Script prerequisites
Portable scripts open with checks: command -v jq >/dev/null || { echo "jq required" >&2; exit 1; }. Failing loudly at line 3 beats failing weirdly at line 300.
Pro tips and common mistakes
- Trust type over which — only type sees aliases, functions and builtins.
- In scripts, command -v is the POSIX-portable existence test.
- New install not taking effect in an old shell? hash -r clears the command cache.
Frequently asked questions about which & type
which shows one thing but something else runs?
An alias or function shadows it — which only searches PATH files. type sees the whole picture; trust type.
How do scripts test for a command?
command -v name — POSIX, silent, exit-code driven. which is unreliable across systems for this.
Related commands
Search, install, upgrade and remove packages — plus the dnf/pacman equivalents.
env & exportHow configuration flows into processes — PATH, export, and why edits "don't stick".
aliasName your habits: shortcuts, safer defaults, and where to keep them.