The Search Path

The Search Path

It may happen that you know there is a program by a particular name on the system, but when you try to start it from the command line, you are told that the file is not found. Because you just ran it yesterday, you assume it has gotten removed or you don’t remember the correct spelling.

The most common reason for this is that the program you want to start is not in your search path. Your search path is a predefined set of directories in which the system looks for the program you type in from the command line (or is started by some other command). This saves time because the system does not have to look through every directory trying to find the program. Unfortunately, if the program is not in one of the directories specified in your path, the system cannot start the program unless you explicitly tell it where to look. To do this, you must specify either the full path of the command or a path relative to where you are currently located.

Lets look at this issue for a minute. Think back to our discussion of files and directories. I mentioned that every file on the system can be referred to by a unique combination of path and file name. This applies to executable programs as well. By inputting the complete path, you can run any program, whether it is in your path or not.

Let’s take a program that is in everyones path, like date (at least it should be). The date program resides in the /bin directory, so its full path is /bin/date. If you wanted to run it, you could type in /bin/date, press Enter and you might get something that looks like this:

Sat Jan 28 16:51:36 PST 1995

However, because date is in your search path, you need to input only its name, without the path, to get it to run.

One problem that regularly crops up for users coming from a DOS environment is that the only place Linux looks for commands is in your path. However, even if not specified in your path, the first place DOS looks is in your current directory. This is not so for Linux. Linux only looks in your path.

For most users, this is not a problem as the current directory is included in your path by default. Therefore, the shell will still be able to execute something in your current directory. The root user typically does not have the current directory in its path. In fact, this is the way it should be. If you want to include the current directory in roots path, make sure it is the last entry in the path so that all “real” commands are executed before any other command that a user might try to “force” on you. In fact, I suggest that every user adds entries to the end of their path.

Assume a malicious user created a “bad” program in his/her directory called more. If root were to run more in that user’s directory, it could have potentially disastrous results. (Note that the current directory normally always appears at the end of the search path. So, even if there was a program called more in the current directory, the one in /bin would probably get executed first. However, you can see how this could cause problems for root.) To figure out exactly which program is actually being run, you can use the (what else?) which command.

Newer versions of the bash-Shell can be configured to not only complete commands automatically by inputting just part of the command, but also arguments to the command, as well as directory names. This is done by pressing the TAB key. See the bash man-page for more details.

Commands can also be starting by including a directory path, whether or not they are in you search path. You can use relative or absolute paths, usually with the same result. Details on this can be found in the section on directory paths.

One very important environment variable is the PATH variable. Remember that the PATH tells the shell where it needs to look when determining what command it should run. One of the things the shell does to make sense of your command is to find out exactly what program you mean. This is done by looking for the program in the places specified by your PATH variable.

Although it is more accurate to say that the shell looks in the directories specified by your PATH environment variable, it is commonly said that the shell “searches your path.” Because this is easier to type, I am going to use that convention.

If you were to specify a path in the command name, the shell does not use your PATH variable to do any searching. That is, if you issued the command bin/date, the shell would interpret that to mean that you wanted to execute the command date that was in the bin subdirectory of your current directory. If you were in / (the root directory), all would be well and it would effectively execute /bin/date. If you were somewhere else, the shell might not be able to find a match.

If you do not specify any path (that is, the command does not contain any slashes), the system will search through your path. If it finds the command, great. If not, you get a message saying the command was not found.

Let’s take a closer look at how this works by looking at my path variable. From the command line, if I type

echo $PATH

I get

/usr/local/bin:/bin:/usr/bin:/usr/X11/bin:/home/jimmo/bin:/:.
WATCH THE DOT!

If I type in date, the first place in which the shell looks is the /bin directory. Because that’s where date resides, it is executed as /bin/date. If I type in vi, the shell looks in /bin, doesn’t find it, then looks in /usr/bin, where it does find vi. Now I type in getdev. (This is a program I wrote to translate major device numbers into the driver name. Don’t worry if you don’t know what a major number is. You will shortly.) The shell looks in /usr/local/bin and doesn’t find it. It then looks in /bin. Still not there. It then tries /usr/bin and /usr/X11/bin and still can’t find it. When it finally gets to /home/jimmo/bin, it finds the getdev command and executes it. (Note that because I wrote this program, you probably won’t have it on your system.)

What would happen if I had not yet copied the program into my personal bin directory? Well, if the getdev program is in my current directory, the shell finds a match with the last “.” in my path. (Remember that the “.” is translated into the current directory, so the program is executed as ./getdev.) If that final “.” was missing or the getdev program was somewhere else, the shell could not find it and would tell me so with something like

getdev: not found

One convention that I (as well as most other authors) will use with is that commands that we talk about will be in your path unless we specifically say otherwise. Therefore, to access them, all you need to do is input the name of the command without the full path.

Note that the search path is not static, you can add directories to it an any time. In fact it is common that the system will define a default search path for all users and then the users will expand in by adding directories in the .profile. For example, to add a personal bin directory the command might look like this:

PATH=$PATH:$HOME/bin

Keep in mind that the shell will expand all variables before executing the command. Therefore, in this example, $PATH and $HOME are expanded before the shell assigns it to PATH.