3
\$\begingroup\$

I am working on improving my bash environment. I have added the following function to my ~/.bashrc in order to facilitate modifying my PATH as well as removing duplicate entries from my PATH which may occur from sourcing ~/.bashrc again.

# $1 the path to be added as an absolute path
# $2 a boolean for whether the path should be prepended. default: false
# $3 the path variable to add to
function addToPath {
    # ${!3} dereferences $3 to use the value the variable refers to. For example $3=PATH would give $PATH
    if [ -z ${3+x} ]; then TMP_PATH="$PATH"; TMP_NAME="PATH"; else TMP_PATH="${!3}"; TMP_NAME="$3"; fi
    if [ ! -d $1 ]; then echo "WARNING: Added $1 to $TMP_NAME but $1 doens't seem to exist"; fi

    case ":$TMP_PATH:" in # Add trailing :'s to cover first and last entries
        *":$1:"*)
            ;; # Exists Already
        *)
            case true in
                $2)
                    TMP_PATH="$1:$TMP_PATH"
                    ;;
                *)
                    TMP_PATH="$TMP_PATH:$1"
                    ;;
            esac
            ;;
    esac

    # Remove potential wrapping ":" chars
    TMP_PATH=${TMP_PATH#":"}
    TMP_PATH=${TMP_PATH%":"}
    if [ -z ${3+x} ]; then export PATH="$TMP_PATH"; else export $3="$TMP_PATH"; fi
}

And then, to build my path and remove duplicates I use the following code.

# Set up basic PATH variable
addToPath /usr/local/bin
addToPath /usr/bin
addToPath /usr/sbin
addToPath /bin
addToPath /sbin

# Remove duplicates from path
NEW_PATH=""
IFS=':' read -r -a path_array <<< "$PATH"
for element in "${path_array[@]}"
do
    addToPath $element false NEW_PATH
done
export PATH=$NEW_PATH
\$\endgroup\$
0

1 Answer 1

3
\$\begingroup\$

Quoting

You should double-quote variables that may contain spaces when used as command arguments. For example here:

addToPath $element false NEW_PATH

You will get strange results if $element contains spaces. Double-quote it, and also in the conditional inside the function:

if [ ! -d "$1" ]; then 

One statement per line

It's easiest to read code from top to bottom, without having to carefully read from left to write too. For this reason it would be better to split the conditionals you crammed on a single line.

Simple solutions are better

The optional third parameter of the function is quite clever, appending to a specified variable instead of the default, at the expense of some added complexity. Instead of all that, you could simply reset PATH after setting path_array and before calling the function. That way you could get rid of the third parameter of the function and its added complexity.

Note also that your function does not add duplicates. So instead of removing duplicates at the end, it will be better to remove duplicates at the beginning, as that will process fewer path elements.

case with two cases

When a switch-construct is used with only two cases, it's usually easier to read converted to an if-else.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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