PATH is the list of directories the shell searches when you type a command — and it is the answer to the entire family of mysteries: "command not found", "why is it running the wrong version", "works in my shell, not in cron". One variable explains all of them.
How lookup works #
Type git and the shell walks PATH left to right, returning the first directory containing an executable named git:
$ echo "$PATH"
/home/ana/.local/bin:/usr/local/bin:/usr/bin:/bin
$ which -a python3
/usr/bin/python3
$ type -a ls # aliases, builtins, and PATH hits together
which -a shows every candidate; type -a adds aliases and builtins. The first hit wins — which is how ~/.local/bin versions override system ones, and how a shadowing binary causes "wrong version" mysteries. See stat, file, and which for the interrogation tools.
Adding to PATH, correctly #
export PATH="$HOME/.local/bin:$PATH" # your bins win
export PATH="$PATH:/opt/tools/bin" # system wins, yours as fallback
The position is the choice: prepending makes your directory authoritative; appending yields to the system. And always reference the old "$PATH" — a bare PATH=... replaces the list and breaks everything downstream.
Persistence is a shell-startup question: ~/.bashrc for interactive bash sessions. The classic self-inflicted wound is exporting in .bash_profile only, then wondering why terminals disagree — one canonical place, sourced once, wins. See alias, function, or script for where scripts should live.
Why "works in my shell" happens #
A cron job, systemd service, or CI runner does not read your .bashrc — it starts with a minimal environment and a short PATH:
$ crontab -l
* * * * * /home/ana/bin/sync.sh
$ # fails: "command not found" for rclone inside sync.sh
The fixes, in order of preference:
| Fix | Form |
|---|---|
| Absolute paths in scripts | /usr/bin/rclone sync ... |
| Set PATH inside the script | export PATH="/usr/local/bin:$PATH" |
| Cron's own PATH line | PATH=/usr/local/bin:/usr/bin:/bin |
| Wrap via login shell | bash -lc '/home/ana/bin/sync.sh' |
Absolute paths are the most robust — they also document exactly what the script calls — with the PATH line a close second for tools with many dependencies.
Scripts that survive cron belong to scheduling; the scripting series continues.
