Should PATH contain directories or full paths to binaries?
I am trying to set up a correct PATH
, but I'm wondering what it should contain. If I have
/usr/bin/ls
/usr/local/bin/ls
and I want to prefer the one in /usr/local/bin
, which of the following should I use?
PATH=/usr/local/bin/ls:/usr/bin/ls
PATH=/usr/local/bin:/usr/bin
or something else entirely?
This is not per se a suitable question for Stack Overflow. I expect this to be closed as General Computing or Too Broad; but the answer is frequently needed by beginners, so I hope this won't be deleted.
PATH
works only with directories, not with single files
From the POSIX standard (emphasis mine)
PATH
This variable shall represent the sequence of path prefixes that certain functions and utilities apply in searching for an executable file known only by a filename. The prefixes shall be separated by a colon ( ':' ). [...] The list shall be searched from beginning to end, applying the filename to each prefix, until an executable file with the specified name and appropriate execution permissions is found.
When you type in ls
into your shell and your PATH
is set to /usr/local/bin/ls:/usr/bin/ls
then your shell will …
… look for an executable with the path
/usr/local/bin/ls/ls
(note the doublels
at the end).As that path does not exist on your system your shell will proceed to look for an executable with the path
/usr/bin/ls/ls
(doublels
again). That path also doesn't exist.The shell couldn't find an executable using all paths in
PATH
so your shell will print something likebash: ls: command not found
.
So, what did we learn? Paths listed by PATH
have to be directories. You cannot list single files. Therefore the correct answer in your case is PATH=/usr/local/bin:/usr/bin
.
Where things get interesting
Imagine the following situation. You have two versions of program c1
and two versions of program c2
. The different versions are stored in the directories /a/
and /b/
.
/a/c1
/a/c2
/b/c1
/b/c2
How can we set PATH
to prefer /a/c1
over /b/c1/
but at the same time /b/c2
over /a/c2
?
Sadly, there is no way to achieve this directly as we can only specify directories in PATH
. We have to move/rename some files or create symlinks and use the symlinks inside the paths. One possible solution:
mkdir /c
ln -s /a/c1 /c/c1
ln -s /b/c2 /c/c2
export PATH=/c:/a:/b
The trailing :/a:/b
is not really necessary here. I included them under the assumption that /a
and /b
contain more executables than just c1
and c2
.
Indeed, as you can easily find out through experimentation, the variable PATH
should already contain a list of directories which are consulted in that order. In fact, you should already find that you have /usr/local/bin
and /usr/bin
in the default PATH
, usually in this order (though perhaps with other directories between them, and certainly with more directories around them).
To inspect your current PATH
value, try
echo "$PATH"
or for a slightly more human-readable rendering
echo "${PATH//:/$'\n'}" # bash only
or
echo "$PATH" | tr ':' '\012' # any POSIX system
If you managed to set your PATH
to an invalid value (which would cause simple commands like ls
and cat
to no longer be found, and produce command not found
errors) you can try
PATH=/usr/local/bin:/usr/bin:/usr
to hopefully at least restore the essential functionality so that you can use cp
or a simple system editor to get back to the original, safe, system default PATH
.