Thursday, February 19, 2015

Creating a portable bash shell profile - Part 1 - auto-cleaning your PATH variable

Customizing a bash shell profile is a basic exercise for someone familiarizing themselves with the Linux environment.  Customizing the PATH variable is a fairly typical step in this process.

One quickly realizes, however, that when setting up a new system, possibly on different variants of Linux or UNIX, repeating this exercise becomes a bit bothersome.  We would like to have a flexible and semi-portable .bash_profile -- one that helps us as much as possible with weeding out missing directories, and eliminating duplicate ones as well.  And of course, we want to do this in bash, without needing to resort to a custom perl or python script to do the heavy lifting.

The following bash script snippet will do just that.  Drop it right into your .bash_profile.  The only special requirement here is that bash 4.0 or above is used.  This allows for the use of associative arrays, which makes testing for duplicate directories simple.  If this is not available, there are a number of ways to work around it.

The script is a bit verbose -- feel free to comment out the echo lines if you want less detail.


# Reset PATH to test and include only desired and existing locations:

# Set up a temporary path:
TPATH=$PATH

# This is where you would add your own 
# custom directories to the default path:
for DIR in \                       
    "/bin" \
    "/usr/bin" \
    "/usr/local/bin" \
    "/sbin" \
    "/usr/sbin" \
    "/usr/local/sbin" \
    "$HOME/bin" \
    "$HOME/scr" \
    "$HOME/scr/midpt" \
    "$HOME/scr/endpt" \
    "$HOME/svn/foo/trunk/Src/src" \
    "$HOME/svn/foo/trunk/Src/src/test"
do
    TPATH="$TPATH:$DIR"
done

# Rebuild PATH from TPATH, testing each directory:
PATH=.

# Declare an associative array/map - bash version 4.0+ required.
declare -A PMAP

# Temporarily change IFS to : to make splitting the PATH trivial:
IFS=:
for DIR in $TPATH
do
    if [ -z "${PMAP[$DIR]}" ]
    then
        if [ -d "${DIR}" ]
        then
            echo "  Adding $DIR to PATH"
            PATH="$PATH:$DIR"
            PMAP[$DIR]=1  # add an entry to our map
        else
            echo "! NOT adding $DIR to PATH -- location does not exist"
        fi
    else
        echo "! NOT adding $DIR to PATH -- duplicate path"
    fi
done
IFS=


Sample output:

Last login: Thu Feb 19 09:31:29 2015 from 10.10.1.247
  Adding /usr/local/sbin to PATH
  Adding /usr/local/bin to PATH
  Adding /usr/sbin to PATH
  Adding /usr/bin to PATH
  Adding /sbin to PATH
  Adding /bin to PATH
  Adding /usr/games to PATH
! NOT adding /bin to PATH -- duplicate path
! NOT adding /usr/bin to PATH -- duplicate path
! NOT adding /usr/local/bin to PATH -- duplicate path
! NOT adding /sbin to PATH -- duplicate path
! NOT adding /usr/sbin to PATH -- duplicate path
! NOT adding /usr/local/sbin to PATH -- duplicate path
  Adding /home/pat/bin to PATH
  Adding /home/pat/scr to PATH
  Adding /home/pat/scr/midpt to PATH
  Adding /home/pat/scr/endpt to PATH
! NOT adding /home/pat/svn/foo/trunk/Src/src to PATH -- location does not exist
! NOT adding /home/pat/svn/foo/trunk/Src/src/test to PATH -- location does not exist


No comments:

Post a Comment