这是典型的在你的.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
Answer 1:
您可以使用下面的Perl脚本进行修剪重复的路径。
#!/usr/bin/perl
#
# ^^ ensure this is pointing to the correct location.
#
# Title: SLimPath
# Author: David "Shoe Lace" Pyke <eselle@users.sourceforge.net >
# : 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 <wayland@ne.com.au> 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;
}
}
我希望这就是有用的。
Answer 2:
林惊讶没有人使用的tr ":" "\n" | grep -x
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"
它具有以下优点:
- 没有bash化或任何特定的外壳的语法。 它以完美运行
!#/bin/sh
(香港专业教育学院与破折号测试) - 多个文件夹可以一次添加
- 没有排序,保存文件夹命令
- 在文件夹名称中的空格优惠完美
- 单个测试工作不管$文件夹是在begginning,结束,中间或者是在$ PATH唯一的文件夹(从而避免测试X:*,*:X,X:X,尽可能多的解决方案,这里隐含做)
- 作品(并保留),如果$ PATH开头或结尾“:”或有“::”它(指当前文件夹)
- 没有
awk
或sed
需要。 - EPA友好;)原IFS值被保留,并且所有其他变量函数的局部范围。
希望帮助!
Answer 3:
OK, 而不是在csh,但是这是我的$ HOME / bin中追加到我在bash路径...
case $PATH in
*:$HOME/bin | *:$HOME/bin:* ) ;;
*) export PATH=$PATH:$HOME/bin
esac
季节的味道...
Answer 4:
我一直在使用以下(伯恩/科恩/ 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;
}'
在Korn shell中,我使用:
export PATH=$(clnpath /new/bin:/other/bin:$PATH /old/bin:/extra/bin)
这给我留下了含有PATH在前面新的和其他的bin目录,加上主路径值的每个目录名的一个副本,除了老的和额外的bin目录已取走。
你将不得不这种适应的C shell(抱歉-但我在所阐述的真理的忠实信徒是有害的C外壳程序 )。 首先,你不会有冒号分隔捣鼓,让生活其实更容易。
Answer 5:
好吧,如果你不在乎什么为了你的路径,你可以这样做:
set path=(`echo $path | tr ' ' '\n' | sort | uniq | tr '\n' ' '`)
这将你的路排序和删除是相同的任何额外的路径。 如果你有 。 在你的路径,你可能想用的grep -v将其删除,并在年底重新添加。
Answer 6:
这是一个漫长的班轮不排序:
集路径=( echo $path | tr ' ' '\n' | perl -e 'while (<>) { print $_ unless $s{$_}++; }' | tr '\n' ' '
)
Answer 7:
Do_peper,
我平时比较喜欢坚持我住在外壳的脚本功能。使之更便于携带。 所以,我使用csh脚本喜欢你的解决方案。 我只是延长它在localdirs每个目录上工作,使之成为自己的工作。
foreach dir ( $localdirs )
echo ${path} | egrep -i "$dir" >& /dev/null
if ($status != 0) then
set path = ( $dir $path )
endif
end
Answer 8:
使用的Sed(1)删除重复。
$ 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
$
请享用!
Answer 9:
下面是我用的 - 也许别人会觉得有用:
#!/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";'
Answer 10:
我总是在.cshrc中设置从头开始我的道路。 这是我开始了一个基本的路径是这样的:
set path = (. ~/bin /bin /usr/bin /usr/ucb /usr/bin/X11)
(取决于系统)。
然后执行:
set path = ($otherPath $path)
添加更多的东西
Answer 11:
我有同样的需求,因为原来的问题。 您以前的答案的基础上,我在科恩/ POSIX /猛砸已经使用:
export PATH=$(perl -e 'print join ":", grep {!$h{$_}++} split ":", "'$otherpath:$PATH\")
我有困难,它直接在csh翻译(CSH逃生规则是疯了)。 我已经使用(由dr_pepper的建议):
set path = ( `echo $otherpath $path | tr ' ' '\n' | perl -ne 'print $_ unless $h{$_}++' | tr '\n' ' '`)
你有想法,以简化它更多(降低管道的数量)?
文章来源: How to keep from duplicating path variable in csh