如何避免在csh中复制路径变量

dr_*_*per 9 csh path-variables path environment-variables

通常在cshrc文件中有类似的东西来设置路径:

set path = ( . $otherpath $path )
Run Code Online (Sandbox Code Playgroud)

但是,当您多次获取cshrc文件时,路径会重复,您如何防止重复?

编辑:这是一种不干净的方式:

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

Mes*_*ion 13

我很惊讶没有人使用tr ":" "\n" | grep -x技术来搜索$ PATH中是否已存在给定的文件夹.有什么理由不去?

一行:

if ! $(echo "$PATH" | tr ":" "\n" | grep -qx "$dir") ; then PATH=$PATH:$dir ; fi
Run Code Online (Sandbox Code Playgroud)

这是一个函数我自己一次向$ 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"
}
Run Code Online (Sandbox Code Playgroud)

它可以在这样的脚本中调用:

append_path "/test:$HOME/bin:/example/my dir/space is not an issue"
Run Code Online (Sandbox Code Playgroud)

它具有以下优点:

  • 没有bashisms或任何特定于shell的语法.它运行完美!#/bin/sh(我用短跑测试)
  • 可以一次添加多个文件夹
  • 没有排序,保留文件夹顺序
  • 与文件夹名称中的空格完美匹配
  • 无论$ folder是在前端,中间还是$ PATH中的唯一文件夹(因此避免测试x:*,*:x,:x:,x,因为这里隐藏的许多解决方案),单个测试都可以工作做)
  • 如果$ PATH以":"开头或结尾,或者其中包含"::"(表示当前文件夹),则工作(并保留)
  • 没有awksed需要.
  • EPA友好;)保留原始IFS值,所有其他变量都是函数范围的本地变量.

希望有所帮助!


Sho*_*ace 3

您可以使用以下 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望那有用。