PATH is the environment variable that tells a Unix or Linux shell which directories to search, and in which order, when a command is typed without a slash in its name. It holds a colon-separated list of absolute directories, such as /usr/local/bin:/usr/bin:/bin, and the first directory containing an executable file with the requested name wins.
In the Shell & terminal context, PATH is one of the most consequential pieces of session state: it decides whether python means the system interpreter or a virtual environment, whether a locally built tool shadows a packaged one, and whether a script run from cron finds its commands at all.
How the shell resolves a command through PATH
When a user types a command, the shell first checks whether the name is an alias, a shell function or a builtin such as cd or echo. Only if none of these match does it consult PATH, scanning the directories from left to right and executing the first matching file with execute permission. If no directory contains the name, the shell reports command not found, usually with exit status 127.
Bash and Zsh speed this up with a hash table of resolved locations, so the search runs once per command name. After a program is installed or moved, the cached entry can point to a stale location; hash -r in Bash or rehash in Zsh clears it. A name containing a slash, such as ./build.sh or /usr/bin/env, bypasses PATH entirely.
The table below lists the lookup order used by Bash for a simple command name.
| Step | What is checked | Example |
|---|---|---|
| 1. Alias | Defined text substitutions | alias ll=’ls -l’ |
| 2. Function | Shell functions in the session | mkcd() { … } |
| 3. Builtin | Commands built into the shell | cd, export, type |
| 4. Hash table | Previously resolved paths | Shown by the hash builtin |
| 5. PATH search | Directories from left to right | /usr/local/bin before /usr/bin |
Typical PATH contents and where they come from
A Linux PATH is assembled from several configuration layers that run at login and when an interactive shell starts. System-wide defaults come from files such as /etc/environment, /etc/profile and scripts in /etc/profile.d, while user additions usually live in ~/.profile, ~/.bashrc or ~/.zshrc.
The common directories have stable conventions derived from the Filesystem Hierarchy Standard.
| Directory | Typical contents | Managed by |
|---|---|---|
| /usr/local/bin | Locally compiled or manually installed tools | Administrator |
| /usr/bin | Programs from distribution packages | Package manager |
| /bin | Essential commands, often a link to /usr/bin | Package manager |
| /usr/sbin | System administration programs | Package manager |
| ~/.local/bin | Per-user tools, for example from pip or pipx | User |
| /snap/bin | Snap package launchers on some systems | snapd |
Most modern distributions have completed the usr merge, so /bin and /sbin are symbolic links into /usr. On those systems duplicate entries in PATH are harmless but add noise when troubleshooting.
Modifying PATH correctly
PATH is changed by reassigning the variable and exporting it, typically by prepending or appending one directory while keeping the existing value. Prepending gives the new directory priority over system commands, while appending makes it a fallback.
| Method | Scope | Persistence |
|---|---|---|
| export PATH=”$HOME/bin:$PATH” | Current shell and its children | Until the shell exits |
| Line in ~/.bashrc or ~/.zshrc | New interactive shells of one user | Permanent for that user |
| Line in ~/.profile | Login sessions, including graphical ones | Permanent for that user |
| Script in /etc/profile.d | Login shells of all users | Permanent, system-wide |
| Environment= in a systemd unit | One service only | Permanent for that unit |
Tools such as Python virtual environments, version managers and language toolchains work largely by prepending their own bin directory to PATH. Activating a virtual environment, for example, places its bin directory first so that python and pip resolve to the isolated interpreter.
To inspect the result, echo "$PATH" prints the list, type -a name shows every match in priority order, and command -v name returns the path that will actually run, which is the portable choice in scripts.
PATH compared with related variables
PATH is only one of several search-path variables with the same colon-separated format, and confusing them is a common source of errors. Each one controls a different kind of lookup.
| Variable | What it searches for | Used by |
|---|---|---|
| PATH | Executable commands | Shells and exec functions |
| LD_LIBRARY_PATH | Shared libraries | Dynamic linker |
| MANPATH | Manual pages | man |
| PYTHONPATH | Python modules | Python interpreter |
| CDPATH | Base directories for cd | Bash and Zsh |
Security risks and common PATH mistakes
Because PATH decides which program runs, it is a security boundary. An attacker who can write to a directory listed early in PATH can plant a malicious program named like a common command and wait for a privileged user to run it.
- Including the current directory as
.or an empty entry, such as a leading colon, lets files in any directory shadow real commands. - World-writable directories in PATH, such as /tmp, allow command hijacking by other users.
- Overwriting instead of extending, as in
PATH=/opt/tool/bin, removes all system commands from the session. - Assuming an interactive PATH in cron, where the default is often only
/usr/bin:/bin, makes scheduled scripts fail. - Relying on user PATH under sudo is unreliable, because sudo commonly applies a fixed secure_path from the sudoers file.
Robust scripts therefore either set PATH explicitly at the top or call critical programs by absolute path, and administrators audit PATH entries for ownership and permissions.
Put simply
PATH is a list of folders the computer checks when someone types the name of a program. It works like a list of shops to visit in a fixed order. The computer goes to the first shop. If the item is not there, it tries the next one.
As soon as it finds a program with the right name, it stops looking. That is why the order of the folders matters. Two programs can share a name, and only the one in the earlier folder is used.
In practice
A data engineer installs a newer version of a command-line tool into ~/.local/bin, but typing the tool name still starts the old packaged version from /usr/bin. Running type -a shows both copies and reveals that ~/.local/bin is appended at the end of PATH in her shell configuration.
She changes the line in ~/.profile to prepend the directory, logs out and back in, and the new version runs. Later, a nightly cron job fails with command not found, because cron does not read her profile. She fixes it by setting PATH explicitly in the crontab, and the job runs reliably from then on.