4

I need to prepend directories to the path variable in my .cshrc file and I want to make sure that the entries are not repeated when compared to existing directories in the path variable. Can someone advise suitable commands for that? The path on my machine is : separated, not space separated.

1
  • I added a reply to complement Stephane answer with a way to "un-duplicate" the PATH automagically (while keeping important binary dirs up front!) Jun 5, 2013 at 15:25

3 Answers 3

4

If on Linux, I suppose your csh is tcsh. Then you should be able to do:

set -f path=("/new/entry" $path:q)

In csh, tcsh and zsh, the $path special array variable is tied to the $PATH scalar environment variable in that the elements of the $path array are constructed by splitting the $PATH variable on the colon character. Any modification of either $path or $PATH is automatically reflected into the other variable.

-f above is to retain only the first entry. $path:q is the elements of $path, quoted, that is preventing word splitting. So the syntax above prepends the /new/entry or moves it to the front if it was already there.

Why would you be using csh though?


Note: the quotes above are necessary. Or more precisely, all the characters in /new/entry need to be quoted one way or another.

set -f path=('/new/'\e"ntry" $path:q)

is OK.

set -f path=(/'new/entry' $path:q)

is not. You can always do it in two stages though:

set path=(/new/entry $path:q)
set -f path=($path:q)

(one of the reasons you may want to stay away from csh)

12
  • 1
    +1 for the "why would you be using csh though?" : please, all csh users, read : faqs.org/faqs/unix-faq/shell/csh-whynot (or the infamous 'Csh-programming considered harmful') May 30, 2013 at 16:31
  • @OlivierDulac That's an argument against csh for scripts, not against csh for interactive use. The real argument against (t)csh for interactive use is that zsh has surpassed tcsh for 20 years, and bash has surpassed tcsh for 10 years, so you should switch to software maintained this century. May 30, 2013 at 22:49
  • Hi Stephane, thanks for a quick answer! The use of csh is not by choice in my case, it is decided by the tools that we use. Can you also suggest a way if the new additions to $PATH are several : delimited directories? Thanks! May 31, 2013 at 7:08
  • @astralsmith, as I said, in (t)csh, the $path array variable is tied to the colon separated scalar variable $PATH. Modifying one will automatically update the other. May 31, 2013 at 7:32
  • Thanks Stephane. It works, although the entries are being repeated and not being moved to the front... May 31, 2013 at 7:53
1

I just add this as a complement to stephane answer: how to get rid of duplicates in $PATH

I'll assume you have

  • directories that should stay in front
  • and other directories as well, order not important (ie, placed AFTER the above)

so:

To un-duplicate entries:

UNIQUE_LIST=$( echo "$PATH" | tr ':' '\n' | sort | uniq)

# then we place in front those from UNIQUELIST that match an ordered list
# note that that way, those who didn't have "/sbin" still won't have it, but if they did
# it will be at the right place in the list
shouldbefirst="/bin /sbin /usr/bin" # complete or re-order as needed on your system...
for dir in $shouldbefirst
do
   if ( echo "$UNIQUE_LIST" | grep "$dir" >/dev/null 2>/dev/null)
   then #we have this dir in UNIQUE_LIST
      NEWLIST="${NEWLIST}:${dir}"
      UNIQUE_LIST="$( echo "$UNIQUE_LIST" | grep -v "^$dir\$")"  #we treated that one, take it out of the original list
   fi
done

# then put the remaining of UNIQUE_LIST in the order you want (here, alphabetically)
for dir in $UNIQUE_LIST
do 
   NEWLIST="${NEWLIST}:${dir}"
   UNIQUE_LIST="$( echo "$UNIQUE_LIST" | grep -v "^$dir\$")"  #we treated that one, take it out of the original list
done

 # get rid of possible first ":" (as NEWLIST starts empty)
 NEWLIST="$(echo "$NEWLIST" | sed -e 's/^://')"

 # and then : (I test by placing "echo" in front, get rid of "echo" if it looks fine)
 echo PATH="$NEWLIST"

(i can not test right now)

NOTE: I'll add recommendation: get rid of "." in your PATH, as it will be "bumped" up to just after the SHOULDBEFIRST dirs ... ("." should always be avoided, and if used, always in the last place only, so that you can't easily bypass commands from /bin, /usr/bin, etc)

2
  • This works. :-) But in my case there are entries that I do not want and I cannot find them anywhere in .zshrc, .zprofile, .bashrc, .bash_profile... I do not know how they get added to PATH :-(
    – PatrickT
    May 21, 2020 at 7:56
  • I found the culprit: private/etc/paths was adding a bunch of things I no longer wished to see.
    – PatrickT
    May 21, 2020 at 16:28
0

I believe that the following can do what you want.

if ( $PATH =~ */some/path* ) then
    set PATH = ($PATH:/some/path)
endif

Note: I'm more of a bash user, so if I have a small error let me know
csh if test

1
  • Hi slm, it did not work in my case. I get "Bad : modifier in $ (/).". May 31, 2013 at 11:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .