up vote 9 down vote favorite
5
share [g+] share [fb]

Has anybody written a bash function to add a directory to $PATH only if it's not already there?

I typically add to PATH using something like:

export PATH=/usr/local/mysql/bin:$PATH

If I construct my PATH in .bash_profile, then it's not read unless the session I'm in is a login session -- which isn't always true. If I construct my PATH in .bashrc, then it runs with each subshell. So if I launch a Terminal window and then run screen and then run a shell script, I get:

$ echo $PATH
/usr/local/mysql/bin:/usr/local/mysql/bin:/usr/local/mysql/bin:....

I'm going to try building a bash function called add_to_path() which only adds the directory if it's not there. But, if anybody has already written (or found) such a thing, I won't spend the time on it.

link|improve this question

See stackoverflow.com/questions/273909/… for some infrastructure that can help. – dmckee Sep 11 '09 at 17:49
feedback

5 Answers

up vote 9 down vote accepted

From my .bashrc:

pathadd() {
    if [ -d "$1" ] && [[ ":$PATH:" != *":$1:"* ]]; then
        PATH="$PATH:$1"
    fi
}

Note that PATH should already be marked as exported, so reexporting is not needed. Also, this adds the new directory to the end of the path; to put at the beginning, use PATH="$1:$PATH" at the obvious place. Finally, this checks whether the directory exists & is a directory before adding it, which you may not care about.

link|improve this answer
1  
I care. – Dennis Williamson Sep 12 '09 at 3:30
1  
This gives an invalid PATH if the original PATH is empty. – bukzor Jul 13 '11 at 18:03
feedback

Here's something from my answer to this question combined with the structure of Doug Harris' function. It uses Bash regular expressions:

add_to_path ()
{
    if [[ "$PATH" =~ (^|:)"${1}"(:|$) ]]
    then
        return 0
    fi
    export PATH=$new_dir:$PATH
}
link|improve this answer
feedback

A simple alias like this one below should do the trick:

alias checkInPath="echo $PATH | tr ':' '\n' | grep -x -c "

All it does is split the path on the : character and compare each component against the argument you pass in. grep checks for a complete line match, and prints out the count.

Sample usage:

$ checkInPath "/usr/local"
1
$ checkInPath "/usr/local/sbin"
1
$ checkInPath "/usr/local/sbin2"
0
$ checkInPath "/usr/local/" > /dev/null && echo "Yes" || echo "No"
No
$ checkInPath "/usr/local/bin" > /dev/null && echo "Yes" || echo "No"
Yes
$ checkInPath "/usr/local/sbin" > /dev/null && echo "Yes" || echo "No"
Yes
$ checkInPath "/usr/local/sbin2" > /dev/null && echo "Yes" || echo "No"
No

Replace the echo command with addToPath or some similar alias/function.

link|improve this answer
Using "grep -x" is probably faster than the loop I put in my bash function. – Doug Harris Sep 11 '09 at 18:04
feedback

Here's what I whipped up:

add_to_path ()
{
    path_list=`echo $PATH | tr ':' ' '`
    new_dir=$1
    for d in $path_list
    do
    	if [ $d == $new_dir ]
    	then
    		return 0
    	fi
    done
    export PATH=$new_dir:$PATH
}

Now in .bashrc I have:

add_to_path /usr/local/mysql/bin
link|improve this answer
feedback

See How to keep from duplicating path variable in csh? on StackOverflow for one set of answers to this question.

link|improve this answer
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.