11

I recently added this line to my .bashrc file so that I could use the java compiler javac from the command line (using MobaXTerm if that makes a difference)

export PATH=$PATH:"/cygdrive/c/Program Files/Java/jdk1.8.0_101/bin" 

But I'm seeing multiple duplicates in my $PATH variable (note that the newlines were only added for readability)

/bin: /drives/c/Users/Justin/DOCUME~1/MobaXterm/slash/bin: /drives/c/WINDOWS: /drives/c/WINDOWS/system32: /cygdrive/c/ProgramFiles/Java/jdk1.8.0_101/bin: /cygdrive/c/ProgramFiles/Java/jdk1.8.0_101/bin: /cygdrive/c/ProgramFiles/Java/jdk1.8.0_101/bin 

Is there something wrong with the way I'm adding to my $PATH?

3
  • Take a look at: unix.stackexchange.com/questions/40749/… Commented May 28, 2017 at 21:21
  • Did you mean to say export PATH=$PATH:"/cygdrive/c/ProgramFiles/Java/jdk1.8.0_101/bin"? Commented May 28, 2017 at 21:23
  • Unless you are repeatedly sourcing your bashrc, then that path should be set once, unless it is being set somewhere else as well. Commented May 28, 2017 at 21:28

2 Answers 2

16

If PATH is manipulated by different scripts that are called by .bashrc, this is usually the result.

While duplicates in PATH aren't a major problem, there are two approaches to keeping PATH free of them:

  1. Check if a dir already exists in PATH before adding
  2. Dedupe PATH as the last step in your .bashrc

Check before adding

javabin="/cygdrive/c/ProgramFiles/Java/jdk1.8.0_101/bin" if ! [[ $PATH =~ "$javabin" ]]; then PATH="$PATH:$javabin" fi 

or write a function:

add_to_path() { local dir re for dir; do re="(^$dir:|:$dir:|:$dir$)" if ! [[ $PATH =~ $re ]]; then PATH="$PATH:$dir" fi done } add_to_path "/cygdrive/c/ProgramFiles/Java/jdk1.8.0_101/bin" 

Dedupe (the best method I found on SO)

PATH="$(perl -e 'print join(":", grep { not $seen{$_}++ } split(/:/, $ENV{PATH}))')" 

See also on Unix & Linux / SuperUser StackExchange:

Sign up to request clarification or add additional context in comments.

3 Comments

Will <<< not put an extra newline at the end of the last path?
Good point, @123. I replaced the awk solution with something more elegant I found here: unix.stackexchange.com/a/149054/201820
Yes, thanks for pointing that out. I have a bash alias that sources my .bashrc
0

There is a function called pathmunge defined in /etc/profile:

pathmunge () { case ":${PATH}:" in *:"$1":*) ;; *) if [ "$2" = "after" ] ; then PATH=$PATH:$1 else PATH=$1:$PATH fi esac } 

Unfortunately, it is also unset at the end of the file. However, just delete the unset line, and you can use it in .bashrc file.

4 Comments

There is no pathmunge function in /etc/profile on my system, and I don't recommend modifying system files like that. It would be better to define pathmunge in your own .bashrc or .bash_profile.
@KeithThompson It's on Redhat, top of the file literally says It's NOT a good idea to change this file unless you know what you are doing. It's much better to create a custom.sh shell script in /etc/profile.d/ to make custom changes to your environment, as this will prevent the need for merging in future updates.
@123: Sure, but it's even better to make custom shell scripts in your home directory. Mucking around in /etc/profile.d makes sense only if you want to make things available to all users on the system. (A lot of systems these days only have one user, but it's still a useful distinction.)
@KeithThompson I wasn't arguing, I was agreeing that /etc/profile shouldn't be changed. I quoted the whole comment but the relevant part was It's NOT a good idea to change this file unless you know what you are doing.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.