将目录添加到$ PATH(如果尚不存在)


126

是否有人编写了bash函数来仅在目录$ PATH中添加目录?

我通常使用类似以下的命令添加到PATH:

export PATH=/usr/local/mysql/bin:$PATH

如果我在.bash_profile中构造PATH,那么除非我所在的会话是登录会话,否则不会读取它-并非总是如此。如果我在.bashrc中构造PATH,那么它将在每个子Shell中运行。因此,如果启动终端窗口,然后运行屏幕,然后运行外壳程序脚本,则会得到:

$ echo $PATH
/usr/local/mysql/bin:/usr/local/mysql/bin:/usr/local/mysql/bin:....

我将尝试构建一个bash函数add_to_path(),该函数仅在目录不存在时才添加目录。但是,如果有人已经写(或发现)了这样的东西,我就不会花时间在上面。


请参阅stackoverflow.com/questions/273909/…以获取一些可以帮助您的基础架构。
dmckee


如果您将问题归结为“仅在尚不存在的情况下添加”,那么当插入的项目在开始时很重要但又不会在此处出现时,您将感到非常惊讶。更好的方法是插入元素,然后删除重复项,因此,如果新条目已经存在,则将其有效地移到开头。
唐·哈奇

Answers:


125

从我的.bashrc中:

pathadd() {
    if [ -d "$1" ] && [[ ":$PATH:" != *":$1:"* ]]; then
        PATH="${PATH:+"$PATH:"}$1"
    fi
}

请注意,PATH应该已经被标记为已导出,因此不需要重新导出。这会在添加目录之前检查该目录是否存在&是目录,您可能并不在意。

同样,这会将新目录添加到路径的末尾。放在开头,请使用PATH="$1${PATH:+":$PATH"}"代替上面的PATH=行。


26
我在乎。
丹尼斯·威廉姆森

4
@Neil:它确实起作用,因为它与":$PATH:"而不是仅仅进行比较"$PATH"
Gordon Davisson

3
@GordonDavisson:很抱歉,我的测试是错误的,您是正确的。
Neil

2
@GordonDavisson大括号中内容的含义是什么。我似乎不${PATH:+"$PATH:"}
解惑

5
@ Mark0978:这就是我为解决bukzor指出的问题所做的工作。${variable:+value}表示检查是否variable已定义并且具有非空值,以及是否给出评估结果value。基本上,如果PATH开头是空白的,则将其设置为"$PATH:$1"; 如果为空白,则将其设置为公正"$1"(请注意缺少冒号)。
戈登·戴维森

19

扩展戈登·戴维森的答案,这支持多个论点

pathappend() {
  for ARG in "$@"
  do
    if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
        PATH="${PATH:+"$PATH:"}$ARG"
    fi
  done
}

所以你可以做pathappend path1 path2 path3 ...

对于前置,

pathprepend() {
  for ((i=$#; i>0; i--)); 
  do
    ARG=${!i}
    if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
        PATH="$ARG${PATH:+":$PATH"}"
    fi
  done
}

与pathappend类似,您可以执行

pathprepend path1 path2 path3 ...


3
这很棒!我做了一个小小的改变。对于“ pathprepend”功能,可以方便地反向读取参数,例如,您可以说出pathprepend P1 P2 P3并以结尾PATH=P1:P2:P3。要获得此行为,请更改for ARG in "$@" dofor ((i=$#; i>0; i--)); do ARG=${!i}
ishmael

感谢@ishmael,好的建议,我编辑了答案。我知道您的评论已有两年多了,但是从那以后我再也没有回来了。我必须弄清楚如何使堆栈交换电子邮件进入我的收件箱!
Guillaume Perrault-Archambault


10

将此内容添加到所选答案的注释中,但注释似乎不支持PRE格式,因此请在此处添加答案:

@ gordon-davisson我不是不必要的引用和串联的忠实拥护者。假设您使用的bash版本> = 3,则可以使用bash的内置正则表达式执行以下操作:

pathadd() {
    if [ -d "$1" ] && [[ ! $PATH =~ (^|:)$1(:|$) ]]; then
        PATH+=:$1
    fi
}

这样可以正确处理目录或PATH中有空格的情况。关于bash的内置正则表达式引擎是否足够慢,以至于它的效率可能不如您的版本所执行的字符串连接和内插有效,所以存在一个问题,但是从某种意义上来说,它对我而言更干净。


1
注释formatting using the backtick仅支持,但您没有任何不错的段落控件。
boatcoder 2013年

这将添加项放在最后。通常希望添加到开头以覆盖现有位置。
丹尼斯·威廉姆森

@DennisWilliamson这是一个公平的观点,尽管我不建议您将其作为默认行为。弄清楚如何更改前缀并不难。
Christopher Smith

@ChristopherSmith-re:unnecessary quoting表示您提前知道$PATH不为null。 "$PATH"可以确定PATH是否为null。类似地,如果$1包含的字符可能会混淆命令解析器。将正则表达式放在引号中"(^|:)$1(:|$)"可以防止这种情况。
杰西·奇斯霍尔姆

@JesseChisholm:实际上,我相信Christopher的观点是[[和之间的规则是不同的]]。我更喜欢引述的一切,都不可能需要被引用,除非导致它失败了,但我相信他是对的,那真的报价没有必要周围$PATH。另一方面,在我看来,您是正确的$1
斯科特,

7
idempotent_path_prepend ()
{
    PATH=${PATH//":$1"/} #delete any instances in the middle or at the end
    PATH=${PATH//"$1:"/} #delete any instances at the beginning
    export PATH="$1:$PATH" #prepend to beginning
}

当您需要$ HOME / bin在$ PATH的开头仅出现一次且无其他地方时,请勿接受任何替代。


谢谢,这是一个很好的解决方案,但是我发现我必须要做PATH=${PATH/"...而不是PATH=${PATH//"...才能使它工作。
Mark Booth

双斜杠形式应匹配任意多个匹配项;单斜杠只匹配第一个(在bash手册页中搜索“模式替换”)。不知道为什么它不起作用……
andybuckley

$1在唯一的条目(没有冒号)的异常情况下,此操作将失败。该条目变为两倍。
丹尼斯·威廉姆森

正如PeterS6g所指出的那样,它也会过于激进地删除。
丹尼斯·威廉姆森

6

这是另一种解决方案,它具有删除冗余整数的其他优点:

function pathadd {
    PATH=:$PATH
    PATH=$1${PATH//:$1/}
}

该函数的单个参数位于PATH的前面,并且同一字符串的第一个实例从现有路径中删除。换句话说,如果目录已经存在于路径中,则将其提升到最前面,而不是作为重复目录添加。

该函数的工作方式是在路径前添加一个冒号,以确保所有条目的前面都有一个冒号,然后将新条目添加到现有路径的前面,并删除该条目。最后一部分使用bash的${var//pattern/sub}符号执行;有关更多详细信息,请参见bash手册


好主意;实施有缺陷。考虑一下,如果您已经拥有/home/robert了自己PATH和您,该怎么办pathadd /home/rob
斯科特,

5

这是我的(我相信它是由我的旧实验室的系统管理员奥斯卡写于多年前的,所有人都应该相信他),它存在于我的bashrc中已有很长时间了。它具有允许您根据需要在新目录之前或之后添加新目录的好处:

pathmunge () {
        if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then
           if [ "$2" = "after" ] ; then
              PATH=$PATH:$1
           else
              PATH=$1:$PATH
           fi
        fi
}

用法:

$ echo $PATH
/bin/:/usr/local/bin/:/usr/bin
$ pathmunge /bin/
$ echo $PATH
/bin/:/usr/local/bin/:/usr/bin
$ pathmunge /sbin/ after
$ echo $PATH
/bin/:/usr/local/bin/:/usr/bin:/sbin/

5

首先,我喜欢@Russell的解决方案,但是有一个小错误:如果您尝试将类似“ / bin”的东西放在“ / sbin:/ usr / bin:/ var / usr / bin:/ usr / local”的路径中/ bin:/ usr / sbin“替换” / bin:“ 3次(当它根本不匹配时)。将针对此问题的修复与来自@ gordon-davisson的附加解决方案相结合,我得到以下信息:

path_prepend() {
    if [ -d "$1" ]; then
        PATH=${PATH//":$1:"/:} #delete all instances in the middle
        PATH=${PATH/%":$1"/} #delete any instance at the end
        PATH=${PATH/#"$1:"/} #delete any instance at the beginning
        PATH="$1${PATH:+":$PATH"}" #prepend $1 or if $PATH is empty set to $1
    fi
}

4

像下面这样的简单别名应该可以解决问题:

alias checkInPath="echo $PATH | tr ':' '\n' | grep -x -c "

它所做的只是在:字符上分割路径,并将每个组件与您传入的参数进行比较。grep检查是否有完整的行匹配,并打印出计数。

用法示例:

$ checkInPath "/usr/local"
1
$ checkInPath "/usr/local/sbin"
1
$ checkInPath "/usr/local/sbin2"
0
$ checkInPath "/usr/local/" > /dev/null && echo "Yes" || echo "No"
No
$ checkInPath "/usr/local/bin" > /dev/null && echo "Yes" || echo "No"
Yes
$ checkInPath "/usr/local/sbin" > /dev/null && echo "Yes" || echo "No"
Yes
$ checkInPath "/usr/local/sbin2" > /dev/null && echo "Yes" || echo "No"
No

将echo命令替换为addToPath或某些类似的别名/函数。


使用“ grep -x”可能比我在bash函数中放入的循环更快。
Doug Harris 2009年


2

这是我的想法:

add_to_path ()
{
    path_list=`echo $PATH | tr ':' ' '`
    new_dir=$1
    for d in $path_list
    do
        if [ $d == $new_dir ]
        then
            return 0
        fi
    done
    export PATH=$new_dir:$PATH
}

现在在.bashrc中,我有:

add_to_path /usr/local/mysql/bin

以下是关于我的原件将如何不处理带空格的目录的评论(感谢此问题指出我使用IFS),从而更新了版本

add_to_path ()
{
    new_dir=$1
    local IFS=:
    for d in $PATH
    do
        if [[ "$d" == "$new_dir" ]]
        then
            return 0
        fi
    done
    export PATH=$new_dir:$PATH
}

1
如果任何目录名称已经在此可能无法PATH包含空格,*?,或[... ]
斯科特,

好点……但是我是一个老派的Linux专家,永远不会使用带有空格的路径:-)
Doug Harris

对您有好处,因为它不会用名称中的空格创建内容。如果编写无法处理它们的代码,您会感到羞耻。作为“老派Linux专家”与它有什么关系?Windoze可能已经普及了这个想法(谢谢,Documents and SettingsProgram Files),但是Unix 在Windoze存在之前就支持包含空格的路径名。
斯科特,

2

我还没有人提到这一点,我感到有些惊讶,但是您可以使用它readlink -f来将相对路径转换为绝对路径,并将其原样添加到PATH中。

例如,要改善Guillaume Perrault-Archambault的答案,

pathappend() {
  for ARG in "$@"
  do
    if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
        PATH="${PATH:+"$PATH:"}$ARG"
    fi
  done
}

变成

pathappend() {
    for ARG in "$@"
    do
        if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]
        then
            if ARGA=$(readlink -f "$ARG")               #notice me
            then
                if [ -d "$ARGA" ] && [[ ":$PATH:" != *":$ARGA:"* ]]
                then
                    PATH="${PATH:+"$PATH:"}$ARGA"
                fi
            else
                PATH="${PATH:+"$PATH:"}$ARG"
            fi
        fi
    done
}

1.基础知识-这有什么用?

readlink -f命令(除其他事项外)会将相对路径转换为绝对路径。这使您可以做类似的事情

$ cd / path / to / my / bin / dir
$ pathappend 
$ echo“ $ PATH”
<您的旧路径>:/ path / to / my / bin / dir

2.为什么我们要两次测试是否在PATH中?

好吧,考虑上面的例子。如果用户第二次 从目录中说出, 将为。当然,不会出现在中。但随后将被设置为 (已等于的绝对路径),该已在中。因此,我们需要避免加入到第二次。pathappend ./path/to/my/bin/dirARG..PATHARGA/path/to/my/bin/dir.PATH/path/to/my/bin/dirPATH

也许更重要的readlink是,顾名思义,它的主要目的是查看符号链接并读出其包含(即指向)的路径名。例如:

$ ls -ld /usr/lib/perl/5.14
-rwxrwxrwx  1   root   root    Sep  3  2015 /usr/lib/perl/5.14 -> 5.14.2
$ readlink /usr/lib/perl/5.14
5.14.2
$ readlink -f /usr/lib/perl/5.14
/usr/lib/perl/5.14.2

现在,如果您说pathappend /usr/lib/perl/5.14,并且您已经/usr/lib/perl/5.14在PATH中,那就好了;我们可以保持原样。但是,如果/usr/lib/perl/5.14您的PATH中还没有包含该代码,则我们调用readlink并获取ARGA= /usr/lib/perl/5.14.2,然后将添加到中PATH。但是请稍等一下-如果您已经说过pathappend /usr/lib/perl/5.14,那么您已经/usr/lib/perl/5.14.2在PATH中了,再次,我们需要检查一下以避免将其添加到PATH第二次。

3.处理什么if ARGA=$(readlink -f "$ARG")

如果不清楚,此行测试是否readlink成功。这只是好的防御性编程实践。如果我们要使用命令m的输出  作为命令  n的一部分(其中m  <  n),则最好检查命令m是否  失败并以某种方式处理。我不认为它会失败-但是,正如如何从OS X 和其他地方检索任意文件的绝对路径中所讨论的那样,它是GNU发明。在POSIX中未指定它,因此它在Mac OS,Solaris和其他非Linux Unix中的可用性值得怀疑。(实际上,我刚读了一条评论,内容为“readlinkreadlinkreadlink -f在Mac OS X 10.11.6上似乎无法正常运行,但realpath可以立即使用。”因此,如果您使用的系统没有readlink,或者在readlink -f无法正常工作的地方,则可以对其进行修改。使用脚本realpath。)通过安装安全网,我们使代码更易于移植。

当然,如果您使用的系统没有readlink(或  realpath),那么您就不会想要这样做。pathappend .

第二个-d测试([ -d "$ARGA" ])实际上可能是不必要的。我想不出$ARG目录可以readlink成功但$ARGA目录不是成功  的任何情况。我只是复制并粘贴了第一个if语句以创建第三个语句,然后-d出于懒惰而将  测试留在那里。

4.还有其他意见吗?

是的 像这里的许多其他答案一样,该函数测试每个参数是否为目录,如果是,则对其进行处理,如果不是,则将其忽略。如果pathappend 仅在“ .”文件(如.bash_profile.bashrc)和其他脚本中使用,这可能(或可能不足够)。但是,如上面答案所示,以交互方式使用它是完全可行的。如果你这样做,你会很困惑

$ pathappend /usr/local/nysql/bin
$ mysql
-bash: mysql: command not found

您是否注意到我nysqlpathappend命令中说的而不是mysql?那pathappend什么也没说。它只是默默地忽略了错误的论点?

就像我在上面说的那样,处理错误是个好习惯。这是一个例子:

pathappend() {
    for ARG in "$@"
    do
        if [ -d "$ARG" ]
        then
            if [[ ":$PATH:" != *":$ARG:"* ]]
            then
                if ARGA=$(readlink -f "$ARG")           #notice me
                then
                    if [[ ":$PATH:" != *":$ARGA:"* ]]
                    then
                        PATH="${PATH:+"$PATH:"}$ARGA"
                    fi
                else
                    PATH="${PATH:+"$PATH:"}$ARG"
                fi
            fi
        else
            printf "Error: %s is not a directory.\n" "$ARG" >&2
        fi
    done
}

(1)您应该添加引号:readlink -f "$ARG"。(2)我不知道为什么会发生这种情况(尤其是在-d "$ARG"测试成功之后),但是您可能想测试是否readlink失败。(3)您似乎忽略了readlink的主要功能-将符号链接名称映射到“真实文件名”。如果(例如)/bin是的符号链接/bin64,则重复调用pathappend /bin可能会导致PATH说…:/bin64:/bin64:/bin64:/bin64:…。您可能还应该检查的新值$ARG是否已经在中PATH
斯科特,

(1)观察良好,我已将其修复。(2)在什么情况下readlink会失败?假定路径是正确的,并且它指向有效位置。(3)我不确定是什么决定了readlink的主要功能,我相信unix文件系统中的大多数(如果不是全部?)路径可以分为两种类型的链接:符号链接和硬链接。至于重复的路径条目,您是对的,但是我的答案并不是要添加它(因为我已经注意到其他答案已经提到了它)。我要添加另一个答案的唯一原因是贡献我认为尚未贡献的内容
qwertyzw

(2)我的意思是,如果至少在意图上隐含/暗示了命令的名称,那么readlink中的“链接”可以指硬链接或软链接。但是,您是对的:man readlink说“ readlink-打印已解析的符号链接或规范文件名”,.在我的示例中,我认为可以将其视为规范文件名。正确?
qwertyzw

(1)对于了解符号链接的人来说,readlink的名称明确表示其目的-它查看符号链接并读出其包含(即指向)的路径名。(2)好吧,我说我不知道为什么readlink会失败。我的基本观点是,如果脚本或函数包含多个命令,并且如果命令m失败(其中m  <  n),则保证命令  n灾难性地失败(或根本没有意义  ),这是一种谨慎的良好做法检查命令m是否失败并以某种方式处理它-至少,…(续)
Scott

(续)…通过诊断中止脚本/功能。假设,readlink如果(a)在您对test和的调用之间目录被重命名或删除(通过另一个进程)readlink,或者(b)如果目录/usr/bin/readlink被删除(或损坏),则可能会失败。(3)您似乎不明白我的意思。我不鼓励您重复其他答案;我是说,通过检查原始内容ARG(从命令行)是否已经存在PATH,而不是重复检查新内容ARG(来自的输出readlink),您的答案是不完整的,因此是不正确的。…(续)
斯科特

1
function __path_add(){  
if [ -d "$1" ] ; then  
    local D=":${PATH}:";   
    [ "${D/:$1:/:}" == "$D" ] && PATH="$PATH:$1";  
    PATH="${PATH/#:/}";  
    export PATH="${PATH/%:/}";  
fi  
}  

1

这样可以正常工作:

if [[ ":$PATH:" != *":/new-directory:"* ]]; then PATH=${PATH}:/new-directory; fi

0

我的版本对空路径的坚持不多,并坚持路径的有效性和目录比此处发布的要少,但是我确实发现了大量prepend / append / clean / unique-ify / etc。shell函数对路径操作很有用。整个状态都位于此处:http : //pastebin.com/xS9sgQsX (非常欢迎反馈和改进!)


0

您可以使用perl一种衬垫:

appendPaths() { # append a group of paths together, leaving out redundancies
    # use as: export PATH="$(appendPaths "$PATH" "dir1" "dir2")
    # start at the end:
    #  - join all arguments with :,
    #  - split the result on :,
    #  - pick out non-empty elements which haven't been seen and which are directories,
    #  - join with :,
    #  - print
    perl -le 'print join ":", grep /\w/ && !$seen{$_}++ && -d $_, split ":", join ":", @ARGV;' "$@"
}

这里是bash:

addToPath() { 
    # inspired by Gordon Davisson, http://superuser.com/a/39995/208059
    # call as: addToPath dir1 dir2
    while (( "$#" > 0 )); do
    echo "Adding $1 to PATH."
    if [[ ! -d "$1" ]]; then
        echo "$1 is not a directory.";
    elif [[ ":$PATH:" == *":$1:"* ]]; then
        echo "$1 is already in the path."
    else
            export PATH="${PATH:+"$PATH:"}$1" # ${x:-defaultIfEmpty} ${x:+valueIfNotEmpty}
    fi
    shift
    done
}


0

您可以检查是否已设置自定义变量,否则可以对其进行设置,然后添加新条目:

if [ "$MYPATHS" != "true" ]; then
    export MYPATHS="true"
    export PATH="$PATH:$HOME/bin:"

    # java stuff
    export JAVA_HOME="$(/usr/libexec/java_home)"
    export M2_HOME="$HOME/Applications/apache-maven-3.3.9"
    export PATH="$JAVA_HOME/bin:$M2_HOME/bin:$PATH"

    # etc...
fi

当然,如果由其他脚本(例如)添加,这些条目仍可以重复/etc/profile


0

此脚本允许您在末尾添加$PATH

PATH=path2; add_to_PATH after path1 path2:path3
echo $PATH
path2:path1:path3

或在以下内容的开头添加$PATH

PATH=path2; add_to_PATH before path1 path2:path3
echo $PATH
path1:path3:path2

# Add directories to $PATH iff they're not already there
# Append directories to $PATH by default
# Based on https://unix.stackexchange.com/a/4973/143394
# and https://unix.stackexchange.com/a/217629/143394
add_to_PATH () {
  local prepend  # Prepend to path if set
  local prefix   # Temporary prepended path
  local IFS      # Avoid restoring for added laziness

  case $1 in
    after)  shift;; # Default is to append
    before) prepend=true; shift;;
  esac

  for arg; do
    IFS=: # Split argument by path separator
    for dir in $arg; do
      # Canonicalise symbolic links
      dir=$({ cd -- "$dir" && { pwd -P || pwd; } } 2>/dev/null)
      if [ -z "$dir" ]; then continue; fi  # Skip non-existent directory
      case ":$PATH:" in
        *":$dir:"*) :;; # skip - already present
        *) if [ "$prepend" ]; then
           # ${prefix:+$prefix:} will expand to "" if $prefix is empty to avoid
           # starting with a ":".  Expansion is "$prefix:" if non-empty.
            prefix=${prefix+$prefix:}$dir
          else
            PATH=$PATH:$dir  # Append by default
          fi;;
      esac
    done
  done
  [ "$prepend" ] && PATH=$prefix:$PATH
}

0

这是一种符合POSIX的方式。

# USAGE: path_add [include|prepend|append] "dir1" "dir2" ...
#   prepend: add/move to beginning
#   append:  add/move to end
#   include: add to end of PATH if not already included [default]
#          that is, don't change position if already in PATH
# RETURNS:
# prepend:  dir2:dir1:OLD_PATH
# append:   OLD_PATH:dir1:dir2
# If called with no paramters, returns PATH with duplicate directories removed
path_add() {
    # use subshell to create "local" variables
    PATH="$(path_unique)"
    export PATH="$(path_add_do "$@")"
}

path_add_do() {
    case "$1" in
    'include'|'prepend'|'append') action="$1"; shift ;;
    *)                            action='include'   ;;
    esac

    path=":$PATH:" # pad to ensure full path is matched later

    for dir in "$@"; do
        #       [ -d "$dir" ] || continue # skip non-directory params

        left="${path%:$dir:*}" # remove last occurrence to end

        if [ "$path" = "$left" ]; then
            # PATH doesn't contain $dir
            [ "$action" = 'include' ] && action='append'
            right=''
        else
            right=":${path#$left:$dir:}" # remove start to last occurrence
        fi

        # construct path with $dir added
        case "$action" in
            'prepend') path=":$dir$left$right" ;;
            'append')  path="$left$right$dir:" ;;
        esac
    done

    # strip ':' pads
    path="${path#:}"
    path="${path%:}"

    # return
    printf '%s' "$path"
}

# USAGE: path_unique [path]
# path - a colon delimited list. Defaults to $PATH is not specified.
# RETURNS: `path` with duplicated directories removed
path_unique() {
    in_path=${1:-$PATH}
    path=':'

    # Wrap the while loop in '{}' to be able to access the updated `path variable
    # as the `while` loop is run in a subshell due to the piping to it.
    # https://stackoverflow.com/questions/4667509/shell-variables-set-inside-while-loop-not-visible-outside-of-it
    printf '%s\n' "$in_path" \
    | /bin/tr -s ':' '\n'    \
    | {
            while read -r dir; do
                left="${path%:$dir:*}" # remove last occurrence to end
                if [ "$path" = "$left" ]; then
                    # PATH doesn't contain $dir
                    path="$path$dir:"
                fi
            done
            # strip ':' pads
            path="${path#:}"
            path="${path%:}"
            # return
            printf '%s\n' "$path"
        }
}

它是从那儿剽窃纪尧姆·佩罗-阿香博的回答了这个问题,并mike511的答案在这里

更新2017-11-23:修复了每个@Scott的错误


我打算为此提供默认值,以提供一个命令行选项供您选择在前置和后置(追加)之间进行投票。但是后来我想:这是很多有些神秘的代码,没有任何解释。(而事实上,你有两个功能,其中一个改变路径,又呼应了新的价值,以及其他捕获输出再次分配到PATH只是一个不必要的复杂性。)...(续)
斯科特

(续)…然后我注意到链接是错误的。(而且我不确定您为什么要责怪那些家伙;您似乎并没有从他们的答案中复制太多内容。)然后,我注意到代码是错误的。我想它可以很好地维护格式正确的PATH,但是不能保证它已经格式正确,尤其是如果您没有启蒙的话/etc/profile。您尝试添加到PATH的目录可能已经存在了不止一次,并且您的代码对此感到窒息。…(续)
斯科特

(续)…例如,如果尝试添加/a/ck/b:/a/ck:/tr:/a/ck,则会得到/a/ck:/b:/a/ck:/tr:/tr:/a/ck
斯科特,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.