What happens when you type a command name?
When you type ls and press Enter, the shell has to find a program called ls somewhere on the disk. It doesn't search the whole computer. It reads a short list of folders, checks each one in order, and runs the first file it finds with that name.
That list lives in an environment variable called PATH. You met environment variables in the previous lesson: named values that every program you start can read. PATH is the one the shell itself relies on most.
A few names never need PATH at all. cd, export, alias and source are built into the shell, because they change the shell's own state. type cd says cd is a shell builtin. Everything else, from ls to git, is a file in one of the PATH folders.
How do you read your PATH?
Print it like any other variable. On this practice laptop it is short:
The colons separate folders. The shell checks /usr/local/bin first, then /usr/bin, then /bin. On a real Linux server the list is often longer, with entries such as /usr/sbin or /snap/bin. On a Mac with Homebrew you'll usually see /opt/homebrew/bin near the front.
Long values are hard to read on one line. Piping through tr puts each folder on its own line, which makes the order obvious.
echo $PATH
/usr/local/bin:/usr/bin:/bin
echo $PATH | tr ":" "\n"
/usr/local/bin
/usr/bin
/binWhat does command not found really mean?
bash: specials: command not found means the shell went through every folder on PATH and none had a file called specials. The file may well exist. It's just somewhere the shell wasn't told to look, such as ~/bin or the folder you're standing in.
There are three usual causes. The program isn't installed. It's installed in a folder that isn't on PATH, which is common right after installing a tool by hand. Or the name is misspelt, and Tab completion would have shown you that.
The shell never searches the current folder by default. Typing specials.sh while standing next to it gives the same error. That's a deliberate safety choice: a file someone drops into a shared folder can't pretend to be ls. To run something in the current folder, type ./specials.sh, which is a path and skips the PATH search entirely.
How do you find out which program will run?
which name prints the full path of the file the shell would run. If it prints nothing, the name isn't on PATH. type name goes further and also reports aliases and builtins, which which doesn't know about.
Run these whenever a command behaves strangely. If python3 gives an unexpected version, which python3 often shows that a second copy in /usr/local/bin is winning over the one in /usr/bin. which -a name lists every match in order, so you can see which copies are hiding behind the first.
which ls
/usr/bin/ls
type specials
specials is /home/you/bin/specialsHow do you add ~/bin to PATH?
A folder called bin in your home folder is the traditional place for your own small scripts. Create it with mkdir -p ~/bin, put scripts there, give them execute permission, and add the folder to PATH:
Read the right-hand side carefully. $HOME/bin is your folder, the colon is the separator, and $PATH is the whole old list. The shell builds the new value from the old one, so every folder that worked before still works. export makes sure programs you start from this shell see the new value too.
Use $HOME here rather than ~. Inside double quotes the shell does not expand ~, so "~/bin:$PATH" would add the literal text ~/bin. Bash happens to cope, but which, scripts run by other shells and most programs would find nothing there.
export PATH="$HOME/bin:$PATH"
echo $PATH
/home/you/bin:/usr/local/bin:/usr/bin:/bin

$HOME/bin in front is what made specials work by name.Why does the order of folders matter?
The search stops at the first match. If two folders both contain specials, the one that appears earlier in PATH wins and the other is ignored without any warning. That's what the Break It task on this page is about: an old copy in ~/old-bin sat in front of the new one.
Putting your folder at the front, as above, lets your scripts override system commands with the same name. That's handy for wrapping a tool, and risky if you name a script ls or test by accident. Putting it at the end (export PATH="$PATH:$HOME/bin") means system commands always win and your scripts are only found when nothing else matches. Either is fine. Pick one and know which you chose.
Whatever you do, keep $PATH in the new value. export PATH=$HOME/bin on its own replaces the whole list, and on a real machine ls, cat and nearly everything else stop working in that terminal until you close it. The practice terminal still finds its built-in commands in that case, so you won't see the damage here.
How do you make the change permanent?
export only changes the shell you typed it into. Open a new terminal and PATH is back to normal. To keep the change, add the same line to ~/.bashrc, the settings file bash reads every time an interactive shell starts. The next lesson covers that file in detail.
Wrap the line in single quotes when you append it. Single quotes stop the shell from expanding $HOME and $PATH now, so the file gets the variable names and works them out fresh each time a terminal opens. With double quotes you'd save today's expanded value, which goes stale.
On a Mac the default shell is zsh, and the file is ~/.zshrc instead. The export line is identical.
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
tail -n 1 ~/.bashrc
export PATH="$HOME/bin:$PATH"What do AI tools get wrong about PATH?
Install instructions written by AI often end with a PATH line. Check three things before you paste it. First, that it keeps $PATH in the value, so nothing else disappears. Second, that it uses >> to append to your settings file and never >, which would erase every other setting in it. Third, that it names the right file for your shell: ~/.bashrc for bash, ~/.zshrc for zsh on a Mac.
They also tend to suggest adding the current folder, ., to PATH so that scripts run without ./. Don't. It means any file in any folder you cd into can be run by accident just by typing its name. Typing ./ is two characters and keeps you in control.
Finally, after a fix, open a new terminal or run source ~/.bashrc and check with which. A PATH line that looks right but points at a folder with a typo fails without any message.
Field notes
- PATH is a list of folders the shell checks, in order, for a command.
- The message command not found means no folder on PATH holds that name.
which nameshows the file that would run.- Add the
exportline to~/.bashrcso the change lasts after closing.
Easy to get wrong
Without :$PATH the new value replaces the whole list. On a real machine, ls, cat and most other commands then say command not found in that terminal.
The shell doesn't expand ~ inside double quotes, so PATH would contain the literal text ~/bin. $HOME is expanded inside double quotes.
One > empties the file before writing, which wipes every other setting in .bashrc. Two >> add to the end.
The current folder isn't on PATH. ./ gives the shell a path, so it runs that exact file without searching.
Questions people ask
Where should my own scripts live?
~/bin is the classic choice, and ~/.local/bin is common on newer Linux systems, where some distributions add it to PATH automatically if it exists. Use one, not both, so you always know where a script came from.
Why does `which` print nothing for `cd`?
cd is built into the shell, so there's no file to find. Use type cd, which reports builtins and aliases as well as programs.
I changed `.bashrc` and nothing happened. Why?
The file is read when a shell starts. Open a new terminal, or run source ~/.bashrc to read it into the current one.
Is PATH the same on a web server?
The idea is identical. Shared hosts often have a shorter PATH and may add folders for the PHP or Node version you choose in the control panel. Run echo $PATH after logging in to see what's there.