$PATH
Remove a path in the elegant way
On POSIX and Unix-like operating systems, the $PATH is specified as a list of directories separated by :
. It’s easy to change the $PATH by hardcoding. However, sometimes it is needed to modify the $PATH programmatically and the most difficult part is removing a path from the $PATH elegantly. The definition of elegant here is using a single line command that is human readable, portable, short and fast. The common idea is using the $IFS, but the $IFS is ugly. Instead of that, I am going to use sed
.
The Idea
I got this idea from jQuery’s .removeClass(). Thank you, jQuery.
Assuming we need to remove /usr/local/bin
from the original $PATH shown as below.
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
First, prepend and append :
to the $PATH.
:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:
Then, replace :/usr/local/bin:
with :
.
:/usr/bin:/bin:/usr/sbin:/sbin:
Now, remove the prepended and appended :
.
/usr/bin:/bin:/usr/sbin:/sbin
Done!
The Code
PATH=`echo ":${PATH}:" | sed -e "s:\:/usr/local/bin\::\::g" -e "s/^://" -e "s/:$//"`
/usr/local/bin
can be replaced with any path or variable containing path.
How it works
- The
echo
command prepends and appends:
to the $PATH. - The
|
pipes the output ofecho
tosed
. - The first
sed
command removes the path. In this command,:
is used as a delimiter, because:
is the only character reserved in the $PATH. As a result, the actual:
in the patterns are escaped as\:
. Although it has some impact on readability, the path to remove will never need to be escaped any more, which means you can use command likesed -e "s:\:${path_to_remove}\::\::g"
without worrying about escaping. - The second and the third
sed
command removes the prepended and appended:
.
The bottom line
If you are using Homebrew, you may like to add this to your shell startup files.
test -x /usr/local/bin/brew && export PATH=/usr/local/bin:`echo ":${PATH}:" | sed -e "s:\:/usr/local/bin\::\::g" -e "s/^://" -e "s/:$//"`