## 35.6. The PATH Environment Variable

Of all the environment variables, the PATH and TERM variables are the most important. The others are often great conveniences, but PATH and TERM can make your life miserable if they get screwed up.

The PATH variable is just a list of directories separated by colon (:) characters. The shell searches through these directories in order whenever it needs to find a command. So, if you want to execute commands in /bin, /usr/bin, /usr/local, the current directory, and your personal bin directory, you would put a line like the one below in your .login file. An empty entry (: as the first or last character, or `::` in the middle) means "the current directory."

`$HOME/bin` Section 7.4

>     setenv PATH /bin:/usr/bin:/usr/local::$HOME/bin

Section 27.6 explains more about setting the path.

The most common problem with PATH is that, somehow, it gets deleted. This usually happens if you try to change PATH and do so incorrectly. When PATH is deleted, your shell can find only its built-in commands (Section 1.9) and commands for which you give the complete pathname. Here's a demonstration:

>     % setenv PATH   Set PATH to null accidentally
>     % ls
>     ls: Command not found.

Needless to say, this can be very frustrating -- especially if you can't figure out what's going on. There are a couple of easy fixes. The easiest is just to log out and log back in again. (logout is a built-in C shell command, so you won't have trouble finding it. If you get an error message like "Not login shell," try exit instead.) Another fix is to read (Section 35.29) whichever initialization file defined your PATH variable, usually .login for C shell users or .profile or .bash_profile for Bourne or bash shell users, respectively:

>     % source ~/.login
>     $ . $HOME/.profile
>     bash$ . $HOME/.bash_profile

This will almost certainly give you some of your path back; the problem is that a lot of initialization files merely add a few "private" directories to a system-wide default path. In this case, just execute the system-wide initialization files first (if your system has them). Their pathnames vary:

>     +$ source /etc/profile
>     $ source /etc/profile.d/*.sh
>     $ source ~/.login
>     bash$ source ~/.bash_profile

Your best bet, if you're unfamiliar with the quirks of your system and how it sets up your shell, is to simply log out and log back in again. Some newer Linux systems, for example, use /etc/profile for bash setup, inheriting the hardwired defaults set by the login command, and then go on to read shell-specific files (often in /etc/profile.d, for example). tcsh and csh are configured using the /etc/csh.login, /etc/csh.cshrc, and other files in /etc/profile.d in similar fashion to bash. This allows package managers to install package specific initialization without modifying (and potentially corrupting) the system's default initialization.

The other common PATH problem is that users sometimes can't find the commands they want. This happens most often when someone writes a new shell script with the same name as a standard Unix command -- say, true. He or she tries to execute it and can't; in fact, all that happens is:

>     % true
>     %

After staring at the script for a long time, the user sometimes gets the right idea: the script is fine; it's the path that's wrong. The PATH variable will look something like this:

>     % printenv PATH
>     /bin:/usr/local/bin:/usr/bin:/sbin::/home/schampeo/bin

The shell searches the PATH in order; therefore, it finds the system's standard true command before seeing the new one. The new command never gets a chance. You could fix this problem by putting the current directory and $HOME/bin at the head of the search path, in which case commands in the current directory and your private bin directory will override the standard commands. However, that's not recommended; it's a well-known security hole.

So what is recommended? Nothing much, except that if you write shell scripts or other programs, give them names that are different from the standard Unix utilities (Section 35.27). If you really need an overlapping name, you can use a relative pathname (Section 1.16) to specify "the program called true in the current directory":

>     % ./true

You can search your PATH for a command with which (Section 2.6), findcmd, and whereiz. Section 35.7 explains the pair of path variables in csh and zsh.

--ML and SJC

Copyright © 2003 O'Reilly & Associates. All rights reserved.