Remove redundant paths from $PATH variable

Viewed 355970

I have defined the same path in the $PATH variable 6 times.

I wasn't logging out to check whether it worked.

How can I remove the duplicates?

The $PATH variable looks like this:

echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin

How would I reset it to just

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
13 Answers

Linux: Remove redundant paths from $PATH variable

Linux From Scratch has this function in /etc/profile

# Functions to help us manage paths.  Second argument is the name of the
# path variable to be modified (default: PATH)
pathremove () {
        local IFS=':'
        local NEWPATH
        local DIR
        local PATHVARIABLE=${2:-PATH}
        for DIR in ${!PATHVARIABLE} ; do
                if [ "$DIR" != "$1" ] ; then
                  NEWPATH=${NEWPATH:+$NEWPATH:}$DIR
                fi
        done
        export $PATHVARIABLE="$NEWPATH"
}

This is intended to be used with these functions for adding to the path, so that you don't do it redundantly:

pathprepend () {
        pathremove $1 $2
        local PATHVARIABLE=${2:-PATH}
        export $PATHVARIABLE="$1${!PATHVARIABLE:+:${!PATHVARIABLE}}"
}

pathappend () {
        pathremove $1 $2
        local PATHVARIABLE=${2:-PATH}
        export $PATHVARIABLE="${!PATHVARIABLE:+${!PATHVARIABLE}:}$1"
}

Simple usage is to just give pathremove the directory path to remove - but keep in mind that it has to match exactly:

$ pathremove /home/username/anaconda3/bin

This will remove each instance of that directory from your path.

If you want the directory in your path, but without the redundancies, you could just use one of the other functions, e.g. - for your specific case:

$ pathprepend /usr/local/sbin
$ pathappend /usr/local/bin
$ pathappend /usr/sbin
$ pathappend /usr/bin
$ pathappend /sbin
$ pathappend /bin
$ pathappend /usr/games

But, unless readability is the concern, at this point you're better off just doing:

$ export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Would the above work in all shells known to man?

I would presume the above to work in sh, dash, and bash at least. I would be surprised to learn it doesn't work in csh, fish', orksh`. I doubt it would work in Windows command shell or Powershell.

If you have Python, the following sort of command should do what is directly asked (that is, remove redundant paths):

$ PATH=$( python -c "
import os
path = os.environ['PATH'].split(':')
print(':'.join(sorted(set(path), key=path.index)))
" )

A one-liner (to sidestep multiline issues):

$ PATH=$( python -c "import os; path = os.environ['PATH'].split(':'); print(':'.join(sorted(set(path), key=path.index)))" )

The above removes later redundant paths. To remove earlier redundant paths, use a reversed list's index and reverse it again:

$ PATH=$( python -c "
import os
path = os.environ['PATH'].split(':')[::-1]
print(':'.join(sorted(set(path), key=path.index, reverse=True)))
" )
  1. Just echo $PATH
  2. copy details into a text editor
  3. remove unwanted entries
  4. PATH= # pass new list of entries

If you just want to remove any duplicate paths, I use this script I wrote a while back since I was having trouble with multiple perl5/bin paths:

#!/bin/bash
#
# path-cleanup
#
# This must be run as "source path-cleanup" or ". path-cleanup"
# so the current shell gets the changes.

pathlist=`echo $PATH | sed 's/:/\n/g' | uniq`

# echo "Starting PATH: $PATH"
# echo "pathlist: $pathlist"
unset PATH
# echo "After unset, PATH: $PATH"
for dir in $pathlist
do
    if test -d $dir ; then
        if test -z $PATH; then
            PATH=$dir
        else
            PATH=$PATH:$dir
        fi
    fi
done
export PATH
# echo "After loop, PATH: $PATH"

And I put it in my ~/.profile at the end. Since I use BASH almost exclusively, I haven't tried it in other shells.

In terminal execute code bellow i want delete java Path PATH=$(tr : '\n' <<<"$PATH" | grep -x -v "/usr/lib/java/bin" | paste -sd:) Here Solution

PATH=echo $PATH | sed 's/:/\n/g' | sort -u | sed ':a;N;$!ba;s/\n/:/g'

Related