Reputation: 1740
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
Upvotes: 154
Views: 408649
Reputation: 2230
With zsh (I love this shell), removing duplicates in the PATH
is as easy as:
typeset -U path
because PATH
(the colon separated list) and path
(the array) are linked by default. But if you want to extend this to something else like the LD_LIBRARY_PATH
, you can associate the list to an array before cleaning:
typeset -T LD_LIBRARY_PATH ld_library_path
typeset -U ld_library_path
Upvotes: 7
Reputation: 1893
In bash you simply can ${var/find/replace}
PATH=${PATH/%:\/home\/wrong\/dir\//}
Or in this case (as the replace bit is empty) just:
PATH=${PATH%:\/home\/wrong\/dir\/}
I came here first but went elsewhere as I thought there would be a parameter expansion to do this. Easier than sed!.
How to replace placeholder character or word in variable with value from another variable in Bash?
Upvotes: 2
Reputation: 1
You can add a line at the beginning of the shell config file:
PATH=
to reset the PATH value before assigning it.
Upvotes: -1
Reputation: 762
Building on Alex Jolig's and GreenFox's one-liner above, and the complaint that AWK wasn't where the script expected it to be (which it is not, on my Mac) I started with
if [[ -x /usr/bin/awk ]]; then
export PATH="$(echo "$PATH" | /usr/bin/awk 'BEGIN { RS=":"; } { sub(sprintf("%c$", 10), ""); if (A[$0]) {} else { A[$0]=1; printf(((NR==1) ?"" : ":") $0) }}')"
echo $PATH
else
echo "AWK is not located at /usr/bin/awk" # for the truly paranoid
fi
Converting this back to a one-liner, it becomes
if [[ -x /usr/bin/awk ]]; then export PATH="$(echo "$PATH" | /usr/bin/awk 'BEGIN { RS=":"; } { sub(sprintf("%c$", 10), ""); if (A[$0]) {} else { A[$0]=1; printf(((NR==1) ?"" : ":") $0) }}')" ; fi
That gives you the protection of making sure that AWK is located where you expect it to be, and you can just toss this line in at the end of your .bashrc or .zshrc file.
Upvotes: 0
Reputation: 11
I defined a function that adds the new directories to the beginning of the path, removes the components that are not a directory and removes the duplicates without changing the order of the remaining directories.
function add_path() {
readarray -t patharray < <(echo $PATH | tr ':' '\n')
uniqpath=()
for dir in "${@}" "${patharray[@]}"; do
if [ -d "${dir}" ] && [[ ! "${uniqpath[@]}" =~ "${dir}" ]]; then
uniqpath+=("${dir}")
fi
done
IFS=: eval 'PATH="${uniqpath[*]}"'
}
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
$ export ORACLE_HOME=/u01/app/oracle/product/19.0.0.0/dbhome_1
$ add_path $ORACLE_HOME/bin $ORACLE_HOME/OPatch
$ echo $PATH
/u01/app/oracle/product/19.0.0.0/dbhome_1/bin:/u01/app/oracle/product/19.0.0.0/dbhome_1/OPatch:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Upvotes: 0
Reputation: 752
This function works well to de-duplicate paths and keeps the order:
### remove dups in $PATH keeping order
# https://sites.google.com/site/jdisnard/path-dupes
function path_de-dup() {
declare -A SPATH
local RET_VAL
local A
local OIFS=$IFS
IFS=':'
for A in ${PATH}
do
[ -z "${SPATH[${A}]}" ] || continue
# By this point no dupe was found
SPATH[${A}]=${#SPATH[*]}
# Reconstruct the $PATH
if [ -z "$RET_VAL" ]
then RET_VAL="$A"
else RET_VAL="${RET_VAL}:${A}"
fi
done
IFS=$OIFS
PATH=$RET_VAL
export PATH
}
Upvotes: 0
Reputation: 3811
Below is a version of this popular answer with additional explanations. It requires you to remove any duplicate or unwanted PATH components by hand. While this isn't very elegant it may often be far simpler and fool-proof.
echo $PATH > path.txt
writes current path to text filenano path.txt
)export PATH=$(cat path.txt)
sets path to be content of the filerm path.txt
removes the fileNote: This is all for your current session, in case you wanted to change PATH permanently, you would have to adapt your bash set-up files (e.g. ~/.bashrc).
Upvotes: 5
Reputation: 1
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
Upvotes: 0
Reputation: 31463
You just execute:
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
that would be for the current session, if you want to change permanently add it to any .bashrc, bash.bashrc, /etc/profile - whatever fits your system and user needs.
Note: This is for Linux. We'll make this clear for new coders. (` , ') Don't try to SET = these.
Upvotes: 142
Reputation: 1367
echo $PATH
PATH= # pass new list of entries
Upvotes: 7
Reputation: 395623
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
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', or
ksh`. 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)))
" )
Upvotes: 24
Reputation: 31
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.
Upvotes: 3
Reputation: 1122
Here is a one line code that cleans up the PATH
Uses /bin/awk
so it works even when PATH is broken
export PATH="$(echo "$PATH" |/bin/awk 'BEGIN{RS=":";}
{sub(sprintf("%c$",10),"");if(A[$0]){}else{A[$0]=1;
printf(((NR==1)?"":":")$0)}}')";
Upvotes: 11
Reputation: 3721
If you're using Bash, you can also do the following if, let's say, you want to remove the directory /home/wrong/dir/
from your PATH
variable:
PATH=`echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//'`
Upvotes: 80
Reputation: 345
For an easy copy-paste template I use this Perl snippet:
PATH=`echo $PATH | perl -pe s:/path/to/be/excluded::`
This way you don't need to escape the slashes for the substitute operator.
Upvotes: 1
Reputation: 143122
How did you add these duplicate paths to your PATH variable? You must have edited one of your .
files. (.tcshrc
, or .bashrc
, etc depending on your particular system/shell). The way to fix it is to edit the file again and remove the duplicate paths.
If you didn't edit any files, and you you must have modified the PATH interactively. In that case the changes won't "stick", ie if you open another shell, or log out and log back in, the changes will be gone automatically.
Note that there are some system wide config files too, but it's unlikely you modified those, so most likely you'll be changing files in your personal home directory (if you want to make those changes permanent once you settle on a set of paths)
Upvotes: 1
Reputation: 328760
There are no standard tools to "edit" the value of $PATH
(i.e. "add folder only when it doesn't already exists" or "remove this folder").
To check what the path would be when you login next time, use telnet localhost
(or telnet 127.0.0.1
). It will then ask for your username and password.
This gives you a new login shell (i.e. a completely new one that doesn't inherit anything from the current environment).
You can check the value of the $PATH
there and edit your rc files until it is correct. This is also useful to see whether you could login again at all after making a change to an important file.
Upvotes: 0
Reputation: 2072
Assuming your shell is Bash, you can set the path with
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
but like Levon said in another answer, as soon as you terminate the shell the changes will be gone. You probably want to set up your PATH
in ~/.bash_profile
or ~/.bashrc
.
Upvotes: 0