================= Shell search PATH ================= - Ian! D. Allen idallen@idallen.ca The shell searches for commands by name in a list of directories. After the shell has processed and removed I/O redirection on a command line, the first token left on the line is assumed to be a command name. Built-in commands (e.g. "cd", "history") are executed directly by the shell. Anything that is not built-in is assumed to be the name of an executable program, and the shell attempts to find a program with that name and run it. (Shells find and run commands.) If the name contains any slashes (e.g. "/bin/date", "foo/bar", "./myprog"), the shell executes that pathname directly. No searching needs to be done. If the name contains no slashes, the shell looks for the executable file in the list of directories kept in the $PATH environment variable. The shell tries each directory, left-to-right, and runs the first executable program it finds. If the same name appears in multiple PATH directories, only the first one found is run. The $PATH variable contains the current list of directories searched by the shell when it tries to find a command name to run. Directories in PATH are separated by colons, e.g. $ echo "$PATH" /bin:/usr/bin:/usr/X11R6/bin:/usr/games:/sbin:/usr/sbin:/usr/bin/X11 A leading or trailing colon, or two adjacent colons ("::"), indicate the current directory in the PATH. (Do not put the current directory in PATH - it is a security risk.) Each entry in PATH should be a directory, not a file name, since the shell will append the command name to it when looking for the command. Because PATH is a shell environment variable, you can change it, and it is inherited by child processes of your shell. How it works: $ PATH=/bin:/usr/bin ; ls - shell tries to find "ls" in first directory in PATH: /bin - shell looks for /bin/ls - this exists, so it is executed $ PATH=/bin:/usr/bin ; gcc - shell tries to find "gcc" in first directory in PATH: /bin - shell looks for /bin/gcc - this is not found - shell tries to find "gcc" in next directory in PATH: /usr/bin - shell looks for /usr/bin/gcc - this exists, so it is executed $ PATH=/bin:/usr/bin ; nosuch - shell tries to find "nosuch" in first directory in PATH: /bin - shell looks for /bin/nosuch - this is not found - shell tries to find "nosuch" in next directory in PATH: /usr/bin - shell looks for /usr/bin/nosuch - this is not found - shell issues message "nosuch: Command not found" $ PATH=/bin:/usr/bin ; /usr/games/fortune - command name /usr/games/fortune contains slashes, $PATH is NOT used - shell executes /usr/games/fortune directly - $PATH is NOT used $ PATH=/bin:/usr/bin ; ./foo - command name contains slashes, $PATH is NOT used - shell executes ./foo directly - $PATH is NOT used Your shell has some built in commands, e.g. echo, cd, umask, pwd, history - built-in commands are not looked up in $PATH $ PATH=/xxjunkxx ; date # fails (because /xxjunkxx/date fails) $ PATH=/xxjunkxx ; pwd # works because pwd is built-in to shell $ PATH=/xxjunkxx ; echo hi # works because echo is built-in to shell $ PATH=/xxjunkxx ; cd .. # works because cd is built-in to shell More examples: $ PATH=/bin:/usr/bin ; ls # works because /bin/ls exists $ PATH=/xxjunkxx ; ls # fails because /xxjunkxx/ls does not exist $ PATH=/bin/ls ; ls # fails because /bin/ls/ls does not exist Commands related to PATH: which - tell which $PATH directory contains a command whereis - locate commands in "standard" directories (ignores $PATH) (also locates man pages for you, if any) Note that "whereis" may tell you that a command exists in some standard directory, but when you try to execute the command it may not be found, if the standard directory is not one of your PATH directories. The shell only looks in PATH, not in any "standard" places. Summary: - only command names without slashes are looked up in $PATH - a command name containing a slash is NOT looked for in $PATH - slashes in a command name mean no PATH lookup; direct try to execute path $ ./a.out # uses the a.out in "."; does not search $PATH $ /bin/ls # executes /bin/ls; does not search $PATH $ ../foo # executes the foo in the parent dir; no $PATH used $ foo # "foo" is looked for in $PATH Put PATH into all your shell scripts and export PATH If you don't set the PATH at the start of your script, the script will inherit the PATH from the person or program that executes your script. The inherited PATH may or may not contain the correct directories needed to find the commands used by your script - your script may fail. Choose PATH in your script to include the system directories that contain the commands your script needs. Directories /bin and /usr/bin are almost always necessary. System scripts may need /sbin and /usr/sbin. GUI programs will need the X11 directories. Choose appropriately for the script.