Read

Module 4 · Finding things

which and the PATH lookup

What actually happens when you type a command name: aliases, builtins, the PATH variable searched left to right, and the tools that tell you which one won.

What you will learn

  • Explain how the shell resolves a command name, from aliases to PATH.
  • Locate programs with `which` and identify builtins with `type` and `command -v`.
  • Run a program that is not in PATH and make one available by placing it in a PATH directory.

When you type ls and press Enter, the shell has to turn that word into something it can run. It checks, in order: is it an alias (lesson 92)? Is it a builtin, a command implemented inside the shell itself, like cd, echo or type? If neither, it walks the directories listed in the PATH variable, from left to right, and runs the first executable file with that name. If none matches, you get not found and exit status 127.

~% echo $PATH
/bin:/sbin:/usr/bin:/usr/sbin
~% which awk
/usr/bin/awk
~% which cd
~% echo $?
1
~% type cd
cd is a shell builtin
~% type ls
ls is /bin/ls
~% ls -l $(which awk)
lrwxrwxrwx    1 root     root            17 Jun  3  2018 /usr/bin/awk -> ../../bin/busybox

PATH

PATH is an ordinary environment variable (lesson 69) holding a list of directories separated by colons. Order matters: if two directories both contain a python, the one listed first wins, which is how a user can override a system program by putting their own bin directory at the front. The current directory is deliberately not in PATH. That is why a script in your working directory must be run as ./script.sh: the ./ is a path, and anything containing a slash skips the PATH search entirely.

Asking where a command comes from

CommandAnswers
which NAMEThe path of the program PATH would run; nothing (status 1) for builtins and unknown names.
which -a NAMEEvery match in PATH, not just the first.
type NAMEWhat the shell will really do: alias, builtin or path.
command -v NAMEA short, script-friendly answer; exit status 0 if the command exists.

which only knows about PATH, so it is the right tool for "where is this program installed?". type is the better question when something behaves strangely, because it also knows about aliases and builtins: if ls suddenly prints colours, type ls might reveal an alias. In this VM, nearly every command is a symbolic link to the single /bin/busybox binary, which decides what to do from the name it was called by; ls -l $(which awk) shows the link.

Making your own command available

There are two ways to run a program by its bare name: put it into a directory that is already in PATH (here /usr/bin is a reasonable choice; real systems prefer /usr/local/bin), or add its directory to PATH: PATH=$PATH:/root/bin. The second only lasts for the current shell; lesson 70 shows how to make it permanent and lesson 93 builds a proper personal bin. Either way the file must be executable (chmod +x, lesson 46).

Commands in this lesson

CommandWhat it does
echo $PATHShow the directories searched for commands.
which NAMEPath of the program that would run.
which -a NAMEAll matches in PATH.
type NAMEAlias, builtin or file: what the shell will do.
command -v NAMEDoes it exist? Script-friendly.
./progRun a program from the current directory.
PATH=$PATH:DIRAdd DIR to PATH for this shell.

Quiz

  1. `which cd` prints nothing. Why?

    • `cd` is not installed
    • `cd` is a shell builtin, not a file in PATH
    • `which` needs root
  2. PATH is `/root/bin:/bin:/usr/bin` and both `/root/bin/ls` and `/bin/ls` exist. Which runs when you type `ls`?

    • `/root/bin/ls`, because it comes first
    • `/bin/ls`, because system programs always win
    • The shell asks which one you want
  3. `backup.sh` is in your current directory and executable, but typing `backup.sh` says `not found`. What do you type?

    • `run backup.sh`
    • `./backup.sh`
    • `which backup.sh`
  4. What exit status does the shell return when a command is not found?

    • 1
    • 127
    • 255
  5. Which command tells you that `ll` is an alias for `ls -l`?

    • `which ll`
    • `type ll`
    • `find / -name ll`

Practice

  1. Find out where the `awk` program lives and write its path, as `which` prints it, into /root/lab/l38/awk-path.txt.

  2. /root/lab/l38/hello is an executable script, but typing `hello` gives `not found`. Make `hello` runnable by its bare name from any shell by copying it into one of the directories already listed in PATH (use /usr/bin).

  3. Ask the shell what kind of command `cd` is.

Open this lesson in the app to do the tasks in a real Linux machine and have them checked.