【问题标题】:Remove redundant paths from $PATH variable从 $PATH 变量中删除冗余路径
【发布时间】:2012-07-23 22:48:12
【问题描述】:

我已经在 $PATH 变量中定义了 6 次相同的路径。

我不是为了检查它是否有效而退出。

如何删除重复项?

$PATH 变量如下所示:

echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin

我如何将它重置为只是

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

【问题讨论】:

标签: linux bash path environment-variables sh


【解决方案1】:

PATH=echo $PATH | sed 's/:/\n/g' | sort -u | sed ':a;N;$!ba;s/\n/:/g'

【讨论】:

    【解决方案2】:

    你只需执行:

    export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
    

    这将用于当前会话,如果您想永久更改,请将其添加到任何 .bashrc、bash.bashrc、/etc/profile - 适合您的系统和用户需要的任何内容。

    注意:这是针对 Linux 的。我们将为新编码人员明确这一点。 (` , ') 不要尝试 SET = 这些。

    【讨论】:

    • 是的,我将它们永久设置在 bash.bashrc 中。那么命令应该是这样的吗? echo 'export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games' >> ~/.bashrc
    • 问题是根据您的操作系统执行一系列配置。您需要确保以后不会覆盖 PATH 变量。最简单的方法(对于一个用户)是在用户的个人 .bashrc 中覆盖它,该 .bashrc 通常位于他的主目录中。
    • 您的命令将 PATH 设置为 - $PATH(PATH 的当前值) + 字符串 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin :/sbin:/bin:/usr/gam‌​es。如果您只想拥有字符串,请从命令中删除 $PATH + 分号 (:)。使用 echo 或手动编辑文件 ~/.bashrc 都没关系。
    • bash.bashrc 文件位于 /etc 文件夹中。它不显示 $PATH 变量,所以我不确定在哪里编辑它
    • 在您的第一条评论中,您回显到 ~/.bashrc(引用:>> ~/.bashrc),而不是 /etc/bash.bashrc。如果要更改特定用户的 PATH,请在 /home//.bashrc 文件中编辑它。 /etc/bash.bashrc 适用于所有用户。
    【解决方案3】:
    1. 只要echo $PATH
    2. 将详细信息复制到文本编辑器中
    3. 删除不需要的条目
    4. PATH= # pass new list of entries

    【讨论】:

    • 我这样做并在每个 ':' 拆分路径变量时手动按下回车键,但不要忘记在拾取换行符时再次手动连接成一个字符串。
    【解决方案4】:

    Linux:从 $PATH 变量中删除冗余路径

    Linux From Scratch 有这个function in /etc/profile

    # Functions to help us manage paths.  Second argument is the name of the
    # path variable to be modified (default: PATH)
    pathremove () {
            local IFS=':'
            local NEWPATH
            local DIR
            local PATHVARIABLE=${2:-PATH}
            for DIR in ${!PATHVARIABLE} ; do
                    if [ "$DIR" != "$1" ] ; then
                      NEWPATH=${NEWPATH:+$NEWPATH:}$DIR
                    fi
            done
            export $PATHVARIABLE="$NEWPATH"
    }
    

    这旨在与这些函数一起使用以添加到路径中,这样您就不会多余地这样做:

    pathprepend () {
            pathremove $1 $2
            local PATHVARIABLE=${2:-PATH}
            export $PATHVARIABLE="$1${!PATHVARIABLE:+:${!PATHVARIABLE}}"
    }
    
    pathappend () {
            pathremove $1 $2
            local PATHVARIABLE=${2:-PATH}
            export $PATHVARIABLE="${!PATHVARIABLE:+${!PATHVARIABLE}:}$1"
    }
    

    简单的用法是只给pathremove 要删除的目录路径 - 但请记住它必须完全匹配:

    $ pathremove /home/username/anaconda3/bin
    

    这将从您的路径中删除该目录的每个实例。

    如果您希望路径中的目录但没有冗余,您可以只使用其他功能之一,例如- 针对您的具体情况:

    $ pathprepend /usr/local/sbin
    $ pathappend /usr/local/bin
    $ pathappend /usr/sbin
    $ pathappend /usr/bin
    $ pathappend /sbin
    $ pathappend /bin
    $ pathappend /usr/games
    

    但是,除非考虑到可读性,否则你最好还是这样做:

    $ export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
    

    上述方法是否适用于人类已知的所有 shell?

    我认为以上内容至少适用于shdashbash。如果得知它在 cshfish', orksh 中不起作用,我会感到惊讶。我怀疑它会在 Windows 命令 shell 或 Powershell 中工作。

    如果你有 Python,下面的命令应该做直接询问的事情(即删除冗余路径):

    $ PATH=$( python -c "
    import os
    path = os.environ['PATH'].split(':')
    print(':'.join(sorted(set(path), key=path.index)))
    " )
    

    单行(回避多行问题):

    $ PATH=$( python -c "import os; path = os.environ['PATH'].split(':'); print(':'.join(sorted(set(path), key=path.index)))" )
    

    上面删除了后面的冗余路径。要删除较早的冗余路径,请使用反转列表的索引并再次反转它:

    $ PATH=$( python -c "
    import os
    path = os.environ['PATH'].split(':')[::-1]
    print(':'.join(sorted(set(path), key=path.index, reverse=True)))
    " )
    

    【讨论】:

    • +1。 pathremove() 是否适用于所有 shell 风格,如 csh、ksh、bash 等?顺便说一句,我在 RHEL 上的 /etc/profile 没有 partremove(),但只有 pathmunge() 。
    • @Tagar 我不保证与所有其他 shell 的兼容性。我建议在您使用的任何外壳上对其进行测试,如果它不适用于您的外壳,您可以使用安装了 Python 的 Python - 我在答案中添加了一些 Python 来描述如何操作。
    • 如果我正确阅读“3.5.3 Shell Parameter Expansion”,${!PATHVARIABLE} 是一种变量间接,但我不确定它在这里是如何工作的。你能解释一下吗?
    • @loxaxs 这是那些 bash 函数中的局部变量,用 local 内置函数声明(只能在函数内部使用。)如果您还有其他问题,您可能应该问一个新问题在网站上(首先搜索它以确保您没有创建完全相同的重复...)。
    • 这是一个非常有趣的答案,感谢您的撰写!然而,清理混乱的 PATH 变量的最初问题似乎并没有得到很好的解决(尽管如此,我承认,当使用这个函数时,一开始就不会以一个混乱的 PATH 结束)。
    【解决方案5】:

    如果您只想删除任何重复的路径,我会使用我之前写的这个脚本,因为我遇到了多个 perl5/bin 路径的问题:

    #!/bin/bash
    #
    # path-cleanup
    #
    # This must be run as "source path-cleanup" or ". path-cleanup"
    # so the current shell gets the changes.
    
    pathlist=`echo $PATH | sed 's/:/\n/g' | uniq`
    
    # echo "Starting PATH: $PATH"
    # echo "pathlist: $pathlist"
    unset PATH
    # echo "After unset, PATH: $PATH"
    for dir in $pathlist
    do
        if test -d $dir ; then
            if test -z $PATH; then
                PATH=$dir
            else
                PATH=$PATH:$dir
            fi
        fi
    done
    export PATH
    # echo "After loop, PATH: $PATH"
    

    最后我把它放在我的 ~/.profile 中。由于我几乎只使用 BASH,因此我没有在其他 shell 中尝试过。

    【讨论】:

    • +1 表示解决方案。顺便说一句,如果它们一个接一个地进入列表,它只会删除重复路径。您可以将 |uniq 更改为 |sort|uniq 来解决此问题,但这会更改路径中所有目录的顺序,我认为这不是一个理想的副作用。
    【解决方案6】:

    这是清理 PATH 的一行代码

    • 它不会打乱 PATH 的顺序,只是删除重复项
    • 对待:并优雅地清空 PATH
    • 没有使用特殊字符,所以不需要转义
    • 使用/bin/awk,因此即使 PATH 被破坏也可以工作

      export PATH="$(echo "$PATH" |/bin/awk 'BEGIN{RS=":";}
      {sub(sprintf("%c$",10),"");if(A[$0]){}else{A[$0]=1;
      printf(((NR==1)?"":":")$0)}}')";
      

    【讨论】:

    • 有人测试过吗?安全吗?
    • 如果您没有安装 awk,它会清理您的路径,我建议您在使用 echo $PATH 之前将您的路径复制到 txt 文件
    • 对我不起作用...我已经安装了 awk,但没有删除一些重复项。
    • 这个有效!除了 awk 在不同的地方。如果您在 bash/zshrc 文件末尾使用此脚本,则可以直接调用 awkexport PATH="$(echo "$PATH" | awk 'BEGIN{RS=":";} {sub(sprintf("%c$",10),"");if(A[$0]){}else{A[$0]=1; printf(((NR==1)?"":":")$0)}}')";
    【解决方案7】:

    如果您使用 Bash,如果您想从 PATH 变量中删除目录 /home/wrong/dir/,也可以执行以下操作:

    PATH=`echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//'`
    

    【讨论】:

    • 这对我很有用,因为在 /etc/profile 中添加了一个我希望排除的目录,但对 /etc 没有写入权限。谢谢:)
    • Protip:您可以在 sed 表达式中使用不同的分隔符来避免 \/ 转义:PATH=$(echo $PATH | sed -e 's|:/home/wrong/dir|$||')
    • 当我想立即拥有新的 PATH 并且不想退出当前终端时,这个技巧很有帮助。但是,为避免搞砸,在将其分配给 PATH 之前,应先尝试使用 PATH 生成命令(即echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//')。
    • 当要删除的路径恰好是$PATH 中的第一个路径时,这将不起作用。使用这个:PATH=$(echo :$PATH: | sed -e 's,:/home/wrong/dir:,:,g' -e 's/^://' -e 's/:$//')
    • 不起作用$ PATH=echo $PATH | sed -e 's/:\/scratch\/sjn\/anaconda\/bin\/python\/$//'`` 用于删除 /scratch/sjn/anaconda/bin/python
    【解决方案8】:

    对于一个简单的复制粘贴模板,我使用这个 Perl sn-p:

    PATH=`echo $PATH | perl -pe s:/path/to/be/excluded::`
    

    这样你就不需要为替代操作符转义斜线了。

    【讨论】:

      【解决方案9】:

      在 bash 中,您只需 ${var/find/replace}

      PATH=${PATH/%:\/home\/wrong\/dir\//}
      

      或者在这种情况下(因为替换位是空的)只是:

      PATH=${PATH%:\/home\/wrong\/dir\/}
      

      我先来这里,但我以为会有parameter expansion 来做这件事。比 sed 容易!

      How to replace placeholder character or word in variable with value from another variable in Bash?

      【讨论】:

      • % 表示匹配,如果在字符串的末尾,# 是开头。
      【解决方案10】:

      您是如何将这些重复的路径添加到 PATH 变量中的?您必须编辑过您的. 文件之一。 (.tcshrc.bashrc 等,具体取决于您的特定系统/外壳)。修复它的方法是再次编辑文件并删除重复的路径。

      如果您没有编辑任何文件,并且您必须以交互方式修改了 PATH。在这种情况下,更改不会“坚持”,即如果您打开另一个 shell,或者注销并重新登录,更改将自动消失。

      请注意,也有一些系统范围的配置文件,但您不太可能修改这些文件,因此您很可能会更改个人主目录中的文件(如果您希望在确定一组后永久更改这些文件)路径)

      【讨论】:

        【解决方案11】:

        没有标准工具可以“编辑”$PATH 的值(即“仅在文件夹不存在时添加”或“删除此文件夹”)。

        要检查下次登录时的路径,请使用telnet localhost(或telnet 127.0.0.1)。然后它会询问您的用户名和密码。

        这为您提供了一个新的登录 shell(即一个不从当前环境继承任何东西的全新登录 shell)。

        您可以在那里检查$PATH 的值并编辑您的rc 文件,直到它正确为止。这对于查看在对重要文件进行更改后是否可以再次登录也很有用。

        【讨论】:

        • 无需输入用户名/密码,只需输入/bin/bash -i。少了很多麻烦。
        【解决方案12】:

        假设你的 shell 是 Bash,你可以设置路径

        export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
        

        但就像 Levon 在另一个答案中所说的那样,一旦您终止 shell,更改就会消失。您可能希望在~/.bash_profile~/.bashrc 中设置您的PATH

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-11-02
          • 2011-03-05
          • 1970-01-01
          • 1970-01-01
          • 2016-07-25
          • 2018-01-01
          • 1970-01-01
          相关资源
          最近更新 更多