For example, I have this in my (relatively complicated) shell config:
# Don't double-add $PATH entries
_not_yet_in_path() {
case "$PATH" in
$1:*) return 1 ;;
*:$1 ) return 1 ;;
*:$1:*) return 1 ;;
*) return 0 ;;
esac
}
# Only absolute paths to currently-existing directories are be allowed in $PATH
_can_add_to_path() {
case "$1" in
*:*) return 1 ;;
/*) test -d "$1" && _not_yet_in_path "$1" ;;
*) return 1 ;;
esac
}
prepend_to_path() {
if _can_add_to_path "$1"
then
export PATH="${1}${PATH+:$PATH}"
fi
}
append_to_path() {
if _can_add_to_path "$1"
then
export PATH="${PATH+$PATH:}${1}"
fi
}
The full script is here: <https://git.sr.ht/~wintershadows/dotfiles/tree/master/item/....>. Feedback is always welcome on how I can make this better! The Zsh version of this is a lot nicer.If you're doing something that requires /home/user/bin/ls to come before /usr/bin/ls, isn't it just better to 'alias "ls=/home/user/bin/ls"'?
It all tends to operate in "layers", mostly governed by the sequence of PATH entries. Usually there are too many individual programs to alias, and often which version I want to use is determined dynamically.
Ultimately doing things the way I do them makes sense for me, but it's definitely not very simple and I wouldn't recommend it for most people.
Edit:
I use a .bashrc.d directory to store all of my bash customizations. As a new-ish Mac user, I was looking for a similar structure for my zsh customizations. Really like your setup - thanks for sharing!
case ":$PATH:" in
*:$1:*) return 1 ;;
*) return 0 ;;
esac
? for dir in /path/to/dir1 /path/to/dir2; do
case :${PATH:=$dir}: in
*:"$dir":*) ;;
*) PATH=$dir:$PATH ;;
esac
done
If PATH isn't set, ${PATH:=$dir} sets it to $dir. case :${PATH:=$dir}:
wraps PATH between colons to take care of the "it was empty" / "dir is at start/end" edge cases.The first case is hit when the PATH contained the directory already (no-op); the second case prepends the new directory to the PATH.