如何防止csh中的path变量重复

如何防止csh中的path变量重复,path,environment-variables,csh,path-variables,Path,Environment Variables,Csh,Path Variables,通常,在cshrc文件中有类似的内容来设置路径: set path = ( . $otherpath $path ) 但是,当您多次获取cshrc文件源时,路径会重复,如何防止重复 编辑:这是一种不干净的做法: set localpaths = ( . $otherpaths ) echo ${path} | egrep -i "$localpaths" >& /dev/null if ($status != 0) then set path = ( . $otherpa

通常,在cshrc文件中有类似的内容来设置路径:

set path = ( . $otherpath $path )
但是,当您多次获取cshrc文件源时,路径会重复,如何防止重复

编辑:这是一种不干净的做法:

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

我总是在.cshrc中从头开始设置路径。 也就是说,我从一条基本路径开始,比如:

set path = (. ~/bin /bin /usr/bin /usr/ucb /usr/bin/X11)
set path=(`echo $path | tr ' ' '\n' | sort | uniq | tr '\n' ' '`)
(取决于系统)

然后做:

set path = ($otherPath $path)

要添加更多内容

,可以使用以下Perl脚本修剪重复的路径


#/usr/bin/perl
#
#^^请确保此项指向正确的位置。
#
#标题:SLimPath
#作者:大卫“鞋带”派克
#:蒂姆·尼尔森
#目的:创建my Environoment path的精简版本,以消除
#重复条目并确保“.”路径是最后一个。
#创建日期:1999年4月1日
#修订历史:
#1999年4月1日:初始测试。。一点也不好吃
#:通过“$ENV”调用检索的路径
#1999年4月7日:蒂姆·纳尔逊发电子邮件给
#工作。
#:使用“推送”添加到阵列
#:使用“join”从列表/数组创建分隔字符串。
#16/02/00:修复了cmd行选项,使外观/效果更好
#2000年2月25日:以冗长程度为导向
#
#
使用Getopt::Std;
次级;
$initial_str=“”;
$debug_mode=“”;
$delim_chr=“:”;
$opt_v=1;
getopts(“v:hd:l:e:s:”);
选择:{
$opt_h&&do{
打印“\n$0[-v级别][-d级别][-l delim](-e varname |-s strname |-h)”;
打印“\n此处:”;
打印“\n-h此帮助”;
打印“\n-d调试级别”;
打印“\n-l分隔符(路径变量之间)”;
打印“\n-e指定环境变量(注意:不包括\$sign)”;
打印“\n-s字符串(即$0-s\$PATH:/looser/bin/)”;
打印“\n-v详细程度(0=安静,1=正常,2=详细)”;
打印“\n”;
出口
};
$opt_d&&do{
printlevel 1,“您选择了调试级别$opt\u d\n”;
$debug_mode=$opt_d;
};
$opt_l&&do{
printlevel 1,“您将用\“$opt_l\”\n”分隔字符串;
$delim_chr=$opt_l;
};
$opt_e&&do{
如果($opt_s){die“不能同时指定env var和string\n”;}
打印级别1,“使用环境变量\“$opt_e\”\n”;
$initial_str=$ENV{$opt_e};
};
$opt_&do{
打印级别1,“使用字符串\“$opt_s\”\n”;
$initial_str=$opt_s;
};
}
如果($#ARGV!=1)和!$opt#e和!$opt#s){
die“无需处理--请尝试$0-h\n”;
}
$what=shift@ARGV;
#使用分隔符分割路径
@dirs=拆分(/$delim\u chr/,$initial\u str);
$dest;
@新路径=();
循环:foreach(@dirs){
#确保目录存在并且是一个目录
如果(!-e){printlevel 1,“$\uu不存在\n”;下一步;}
#如果目录为,则设置$dot并再次遍历
如果($\ueq'.'){$dot=1;next;}
#如果($\une`realpath$\u`){
#打印级别2,“$”变为“`realpath$”。\n”;
#   }
未定义$dest;
#$\=Stdlib::realpath($\$dest);
#检查重复项和点路径
foreach$adir(@newpath){if($\eq$adir){
打印级别2,“重复:$\n”;
下一个循环;
}}
推送@newpath,$\ux;
}
#Join从由第一个表达式分隔的列表/数组中创建字符串
打印连接($delim_chr,@newpath)。($dot?$delim_chr.。\n):“\n”);
printlevel 1,“感谢您使用$0\n”;
出口
子打印级别{
我的($level,$string)=@;
如果($opt_v>=$level){
打印STDERR$string;
}
}


我希望这是有用的。

好的,在csh中不是,但这就是我在bash中将$HOME/bin附加到路径的方式

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

品尝季节…

十年来,我一直在使用以下(Bourne/Korn/POSIX/Bash)脚本:

:   "@(#)$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;
}'
这就给了我一个包含新的和其他bin目录的路径,加上主路径值中每个目录名的一个副本,除了旧的和额外的bin目录已经删除了bin之外


您必须将其改编为C shell(对不起,但我非常相信在中阐述的真理)。基本上,您不必摆弄冒号分隔符,因此生活实际上更轻松。

如果您不在乎路径的顺序,您可以执行以下操作:

set path = (. ~/bin /bin /usr/bin /usr/ucb /usr/bin/X11)
set path=(`echo $path | tr ' ' '\n' | sort | uniq | tr '\n' ' '`)

这将对路径进行排序,并删除所有相同的额外路径。如果你有。在您的路径中,您可能希望使用grep-v删除它,并在末尾重新添加它。

这里有一个没有排序的长单行程序:
设置路径=(
echo$path | tr''\n'| perl-e'while(){print$|除非$s{$}++}'| tr'\n'

dr|peper

我通常更喜欢使用我所居住的shell的脚本功能。使它更便于携带。所以,我喜欢使用csh脚本的解决方案。我只是将它扩展到LocalDir中的per-dir,使其适合我自己

foreach dir ( $localdirs ) echo ${path} | egrep -i "$dir" >& /dev/null if ($status != 0) then set path = ( $dir $path ) endif end foreach dir($localdirs) echo${path}|egrep-i“$dir”>&/dev/null 如果($status!=0),则 设置路径=($dir$path) 恩迪夫 结束
我很惊讶没有人使用
tr:“\n”| grep-x
技术来搜索$PATH中是否已经存在给定文件夹。有什么理由不这样做吗

第1行:

if ! $(echo "$PATH" | tr ":" "\n" | grep -qx "$dir") ; then PATH=$PATH:$dir ; fi
下面是我自己制作的一个函数,用于将多个文件夹同时添加到$PATH(使用“aaa:bbb:ccc”符号作为参数),在添加之前检查每个文件夹是否重复:

append_path()
{
    local SAVED_IFS="$IFS"
    local dir
    IFS=:
    for dir in $1 ; do
        if ! $( echo "$PATH" | tr ":" "\n" | grep -qx "$dir" ) ; then
            PATH=$PATH:$dir
        fi
    done
    IFS="$SAVED_IFS"
}
它可以在如下脚本中调用:

append_path "/test:$HOME/bin:/example/my dir/space is not an issue"
它有以下优点:

  • 没有bashism或任何特定于shell的语法。它与
    一起完美运行#/bin/sh
    (我已经用破折号测试过了)
  • 可以一次添加多个文件夹
  • 不排序,保留文件夹顺序
  • 完美处理文件夹名称中的空格
  • 无论$folder是否位于beginning、end、middle或是$PATH中的唯一文件夹,单个测试都有效(因此避免了测试x:*、:x、:x:、x,这里的许多解决方案都隐式地进行了测试)
  • 如果$PATH开始或结束,则工作(并保留)
    $ PATH=$(echo $PATH | sed -e 's/$/:/;s/^/:/;s/:/::/g;:a;s#\(:[^:]\{1,\}:\)\(.*\)\1#\1\2#g;ta;s/::*/:/g;s/^://;s/:$//;')
    
    $ NEWPATH=/bin:/usr/bin:/bin:/usr/local/bin:/usr/local/bin:/bin
    $ echo $NEWPATH | sed -e 's/$/:/; s/^/:/; s/:/::/g; :a; s#\(:[^:]\{1,\}:\)\(.*\)\1#\1\2#g; t a; s/::*/:/g; s/^://; s/:$//;'
    /bin:/usr/bin:/usr/local/bin
    $
    
    #!/bin/csh
    #  ABSTRACT
    #    /bin/csh function-like aliases for manipulating environment
    #    variables containing paths.
    #
    #  BUGS
    #    - These *MUST* be single line aliases to avoid parsing problems apparently related
    #      to if-then-else
    #    - Aliases currently perform tests in inefficient in order to avoid parsing problems
    #    - Extremely fragile - use bash instead!!
    #
    #  AUTHOR
    #    J. P. Abelanet - 11/11/10
    
    #  Function-like alias to add a path to the front of an environment variable
    #    containing colon (':') delimited paths, without path duplication
    #
    #  Usage: prepend_path ENVVARIABLE /path/to/prepend
    alias prepend_path \
      'set arg2="\!:2";  if ($?\!:1 == 0) setenv \!:1 "$arg2";  if ($?\!:1 && $\!:1 !~ {,*:}"$arg2"{:*,}) setenv \!:1 "$arg2":"$\!:1";'
    
    #  Function-like alias to add a path to the back of any environment variable 
    #    containing colon (':') delimited paths, without path duplication
    #
    #  Usage: append_path ENVVARIABLE /path/to/append
    alias append_path \
      'set arg2="\!:2";  if ($?\!:1 == 0) setenv \!:1 "$arg2";  if ($?\!:1 && $\!:1 !~ {,*:}"$arg2"{:*,}) setenv \!:1 "$\!:1":"$arg2";'
    
    export PATH=$(perl -e 'print join ":", grep {!$h{$_}++} split ":", "'$otherpath:$PATH\")
    
    set path = ( `echo $otherpath $path | tr ' ' '\n' | perl -ne 'print $_ unless $h{$_}++' | tr '\n' ' '`)