views:

1433

answers:

7

It is typical to have something like this in your cshrc file for setting the path:

set path = ( . $otherpath $path )

but, the path gets duplicated when you source your cshrc file multiple times, how do you prevent the duplication?

EDIT:
This is one unclean way of doing it:

set localpaths = ( . $otherpaths )
echo ${path} | egrep -i "$localpaths" >& /dev/null
if ($status != 0) then
set path = ( . $otherpaths $path )
endif

+1  A: 

I always set my path from scratch in .cshrc. That is I start off with a basic path, something like:

set path = (. ~/bin /bin /usr/bin /usr/ucb /usr/bin/X11)

(depending on the system).

And then do:

set path = ($otherPath $path)

to add more stuff

Andrew Stein
+1  A: 

you can use the following Perl script to prune paths of duplicates.


#!/usr/bin/perl
#
# ^^ ensure this is pointing to the correct location.
#
# Title:    SLimPath
# Author:   David "Shoe Lace" Pyke <[email protected] >
#   : Tim Nelson 
# Purpose: To create a slim version of my envirnoment path so as to eliminate
#    duplicate entries and ensure that the "." path was last.
# Date Created: April 1st 1999
# Revision History:
#   01/04/99: initial tests.. didn't wok verywell at all
#    : retreived path throught '$ENV' call
#   07/04/99: After an email from Tim Nelson <[email protected]> got it to
#      work.
#    : used 'push' to add to array
#    : used 'join' to create a delimited string from a list/array.
#   16/02/00: fixed cmd-line options to look/work better
#   25/02/00: made verbosity level-oriented
#
#

use Getopt::Std;

sub printlevel;

$initial_str = "";
$debug_mode = "";
$delim_chr = ":";
$opt_v = 1;

getopts("v:hd:l:e:s:");

OPTS: {
    $opt_h && do {
print "\n$0 [-v level] [-d level] [-l delim] ( -e varname | -s strname | -h )";
print "\nWhere:";
print "\n   -h This help";
print "\n   -d Debug level";
print "\n   -l Delimiter (between path vars)";
print "\n   -e Specify environment variable (NB: don't include \$ sign)";
print "\n   -s String (ie. $0 -s \$PATH:/looser/bin/)";
print "\n   -v Verbosity (0 = quiet, 1 = normal, 2 = verbose)";
print "\n";
     exit;
    };
    $opt_d && do {
     printlevel 1, "You selected debug level $opt_d\n";
     $debug_mode = $opt_d;
    };
    $opt_l && do {
     printlevel 1, "You are going to delimit the string with \"$opt_l\"\n";
     $delim_chr = $opt_l;
    };
    $opt_e && do {
     if($opt_s) { die "Cannot specify BOTH env var and string\n"; }
     printlevel 1, "Using Environment variable \"$opt_e\"\n";
     $initial_str = $ENV{$opt_e};
    };
    $opt_s && do {
     printlevel 1, "Using String \"$opt_s\"\n";
     $initial_str = $opt_s;
    };
}

if( ($#ARGV != 1) and !$opt_e and !$opt_s){
    die "Nothing to work with -- try $0 -h\n";
}

$what = shift @ARGV;
# Split path using the delimiter
@dirs = split(/$delim_chr/, $initial_str);

$dest;
@newpath = ();
LOOP: foreach (@dirs){
    # Ensure the directory exists and is a directory
    if(! -e ) { printlevel 1, "$_ does not exist\n"; next; }
    # If the directory is ., set $dot and go around again
    if($_ eq '.') { $dot = 1; next; }

#   if ($_ ne `realpath $_`){
#           printlevel 2, "$_ becomes ".`realpath $_`."\n";
#   }
    undef $dest;
    #$_=Stdlib::realpath($_,$dest);
    # Check for duplicates and dot path
    foreach $adir (@newpath) { if($_ eq $adir) { 
     printlevel 2, "Duplicate: $_\n";
     next LOOP; 
    }}

    push @newpath, $_;
}

# Join creates a string from a list/array delimited by the first expression
print join($delim_chr, @newpath) . ($dot ? $delim_chr.".\n" : "\n");

printlevel 1, "Thank you for using $0\n";
exit;

sub printlevel {
    my($level, $string) = @_;

    if($opt_v >= $level) {
     print STDERR $string;
    }
}


i hope thats useful.

ShoeLace
+2  A: 

ok, not in csh, but this is how I append $HOME/bin to my path in bash...

case $PATH in
    *:$HOME/bin | *:$HOME/bin:* ) ;;
    *) export PATH=$PATH:$HOME/bin
esac

season to taste...

mike511
+2  A: 

I've been using the following (Bourne/Korn/POSIX/Bash) script for most of a decade:

:   "@(#)$Id: clnpath.sh,v 1.6 1999/06/08 23:34:07 jleffler Exp $"
#
#   Print minimal version of $PATH, possibly removing some items

case $# in
0)  chop=""; path=${PATH:?};;
1)  chop=""; path=$1;;
2)  chop=$2; path=$1;;
*)  echo "Usage: `basename $0 .sh` [$PATH [remove:list]]" >&2
    exit 1;;
esac

# Beware of the quotes in the assignment to chop!
echo "$path" |
${AWK:-awk} -F: '#
BEGIN   {   # Sort out which path components to omit
            chop="'"$chop"'";
            if (chop != "") nr = split(chop, remove); else nr = 0;
            for (i = 1; i <= nr; i++)
                omit[remove[i]] = 1;
        }
{
    for (i = 1; i <= NF; i++)
    {
        x=$i;
        if (x == "") x = ".";
        if (omit[x] == 0 && path[x]++ == 0)
        {
            output = output pad x;
            pad = ":";
        }
    }
    print output;
}'

In Korn shell, I use:

export PATH=$(clnpath /new/bin:/other/bin:$PATH /old/bin:/extra/bin)

This leaves me with PATH containing the new and other bin directories at the front, plus one copy of each directory name in the main path value, except that the old and extra bin directories have bin removed.

You would have to adapt this to C shell (sorry - but I'm a great believer in the truths enunciated at C Shell Programming Considered Harmful). Primarily, you won't have to fiddle with the colon separator, so life is actually easier.

Jonathan Leffler
+2  A: 

Well, if you don't care what order your paths are in, you could do something like:

set path=(`echo $path | tr ' ' '\n' | sort | uniq | tr '\n' ' '`)

That will sort your paths and remove any extra paths that are the same. If you have . in your path, you may want to remove it with a grep -v and re-add it at the end.

Steve Baker
The only problem I see with this is that it will alter the path order, but I do like the fact that it is a one-liner.
dr_pepper
+2  A: 

Here is a long one-liner without sorting:
set path = ( echo $path | tr ' ' '\n' | perl -e 'while (<>) { print $_ unless $s{$_}++; }' | tr '\n' ' ')

dr_pepper
A: 
Madhur Kashyap