How can I cleanly add to $PATH?

Suppose that the new path that we want to add is:

new=/opt/bin

Then, using any POSIX shell, we can test to see if new is already in the path and add it if it isn't:

case ":${PATH:=$new}:" in
    *:"$new":*)  ;;
    *) PATH="$new:$PATH"  ;;
esac

Note the use of colons. Without the colons, we might think that, say, new=/bin was already in the path because it pattern matched on /usr/bin. While PATHs normally have many elements, the special cases of zero and one elements in the PATH is also handled. The case of the PATH initially having no elements (being empty) is handled by the use of ${PATH:=$new} which assigns PATH to $new if it is empty. Setting default values for parameters in this way is a feature of all POSIX shells: see section 2.6.2 of the POSIX docs.)

A callable function

For convenience, the above code can be put into a function. This function can be defined at the command line or, to have it available permanently, put into your shell's initialization script (For bash users, that would be ~/.bashrc):

pupdate() { case ":${PATH:=$1}:" in *:"$1":*) ;; *) PATH="$1:$PATH" ;; esac; }

To use this path update function to add a directory to the current PATH:

pupdate /new/path

Create a file in /etc/profile.d called, e.g., mypath.sh (or whatever you want). If you are using lightdm, make sure that's viable or else use /etc/bashrc or a file sourced from same. Add to that the following functions:

checkPath () {
        case ":$PATH:" in
                *":$1:"*) return 1
                        ;;
        esac
        return 0;
}

# Prepend to $PATH
prependToPath () {
        for a; do
                checkPath $a
                if [ $? -eq 0 ]; then
                        PATH=$a:$PATH
                fi
        done
        export PATH
}

# Append to $PATH
appendToPath () {
        for a; do
                checkPath $a
                if [ $? -eq 0 ]; then
                        PATH=$PATH:$a
                fi
        done
        export PATH
}

Things at the beginning of (prepended to) $PATH take precedence over what follows, and conversely, things at the end (appended) will be superseded by what comes before. This means if your $PATH is /usr/local/bin:/usr/bin and there is an executable gotcha in both directories, the one in /usr/local/bin will be used by default.

You can now -- in this same file, in another shell config file, or from the commandline -- use:

appendToPath /some/path /another/path
prependToPath /some/path /yet/another/path

If this is in a .bashrc, it will prevent the value from appearing more than once when you start a new shell. There is a limitation in that if you want to append something that was prepended (i.e. move a path within $PATH) or vice versa, you'll have to do it yourself.


You can do it this way:

echo $PATH | grep /my/bin >/dev/null || PATH=$PATH:/my/bin

Note: if you build PATH from other variables, do check that they're not empty, for many shells interpret "" like "." .

Tags:

Shell

Path