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

151

我在$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

你在哪里定义了它6次?在哪些文件中? - hovanessyan
3
可能是重复的问题:What is the most elegant way to remove a path from the $PATH variable in Bash? - Ciro Santilli OurBigBook.com
19个回答

138

您只需执行:

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 - charles hendry
问题在于,根据您的操作系统,会执行一系列配置。您需要确保 PATH 变量不会被后续覆盖。最简单的方法(针对一个用户)是在用户个人的 .bashrc 文件中进行覆盖,该文件通常位于其主目录中。 - hovanessyan
1
你的命令将PATH设置为$PATH(当前PATH的值)+字符串/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games。如果你只想获取字符串,从你的命令中移除$PATH和分号(:)即可。无论是使用echo还是手动编辑文件~/.bashrc都可以。 - hovanessyan
bash.bashrc文件位于/etc文件夹中。虽然它不显示$PATH变量,但我不确定在哪里编辑它。 - charles hendry
在你的第一个评论中,你回显到~/.bashrc(引用:>> ~/.bashrc),而不是/etc/bash.bashrc。如果你想为特定用户更改PATH,请在/home/<用户名>/.bashrc文件中进行编辑。/etc/bash.bashrc适用于所有用户。 - hovanessyan
我认为这不是正确的答案。问题是要删除重复项,而不仅仅是设置最终路径。 - Honghao Z

78

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

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

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

1
这对我很有用,因为在 /etc/profile 中添加了一个我希望排除的目录,但我没有写入 /etc 的访问权限。谢谢 :) - Samizdis
18
专业提示:您可以在sed表达式中使用不同的分隔符来避免/转义:PATH=$(echo $PATH | sed -e 's|:/home/wrong/dir|$||') - iNecas
4
这个技巧可以立即生成新的PATH,而无需注销当前终端。但是,为了避免出错,应该在将其分配给PATH之前尝试使用PATH生成命令(即echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//')。 - biocyberman
2
当要删除的路径恰好是 $PATH 中的第一个路径时,这种方法不起作用。请使用以下命令:PATH=$(echo :$PATH: | sed -e 's,:/home/wrong/dir:,:,g' -e 's/^://' -e 's/:$//') - Robin Hsu
我尝试了Stefan van den Akker、iNecas、biocyberman和user3804598。由于在每次尝试后我没有关闭和重新打开终端,所以在每次尝试后我没有看到任何变化。因此,我无法确定哪个版本最终完成了工作。我的感觉是,它应该是user3804598,因为这是我最后尝试的,但我不确定。无论如何,在这里感谢所有的贡献! - soirbleu
显示剩余3条评论

23

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

Linux From Scratch在/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中可以使用上述方法。如果它不能在cshfishksh中使用,那么我会感到惊讶。我怀疑它无法在Windows命令行或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
@Tagar 我不能保证它与所有其他shell兼容。我建议在你正在使用的任何shell上进行测试,如果它不适用于你的shell,你可以使用Python(如果已安装)-我添加了一些Python来描述如何操作。 - Russia Must Remove Putin
@loxaxs 这些 bash 函数中的变量是局部变量,使用 local 内置命令声明(该命令只能在函数内部使用)。如果您有进一步的问题,您应该在网站上提出一个新问题(在首先搜索以确保您不会创建完全重复的问题之后...)。 - Russia Must Remove Putin
这是一个非常有趣的答案,感谢您的撰写!然而,清理混乱的PATH变量的原始问题似乎没有得到优雅的解决(尽管我承认,当使用这些函数时,一开始就不会出现混乱的PATH)。 - Christian Herenz
${!PATHVARIABLE}间接引用结构在dash中不起作用。没关系,我只使用$PATH。即使在2021年,这仍然很重要,因为Ubuntu中的KDE自动启动登录脚本是由dash运行的,如果您想要一个路径设置应用于用户级别的整个DE,则必须将其放入自动启动登录脚本中。 - JohnLittle
如何更改一行命令以适应XDG_DATA_DIRS? - Estatistics
显示剩余3条评论

11

这是一行代码,可以清理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)}}')";

1
有人测试过吗?安全吗? - Joe RR
2
如果您没有安装awk,它会清除您的路径,我建议在执行命令之前使用echo $PATH将您的路径复制到txt文件中。 - Gabriel Pita
对我不起作用...我已经安装了awk,但是一些重复项没有被删除。 - Christian Herenz
1
这个可以工作!只是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)}}')"; - Honghao Z
我已在Mac上测试了以下一行代码。如果awk不在预期位置,则脚本无法运行。如果[[ -x /usr/bin/awk ]];则导出PATH =“ $(echo”$ PATH“| / usr / bin / awk'BEGIN {RS =“:”; } {sub(sprintf(”%c $“,10),“”); if(A [$ 0]){} else {A [$ 0] = 1; printf(((NR == 1)?“”:“:”)$ 0)}}}'); fi - A. Rick

6
  1. 只需输入echo $PATH
  2. 将详细信息复制到文本编辑器中
  3. 删除不需要的条目
  4. PATH= #传递新的条目列表

我曾经这样做,手动在每个“:”处分割路径变量,但不要忘记手动将它们连接成一个字符串,因为会捕捉到换行符。 - mLstudent33

3

简单易行

以下是这个流行答案的一个版本,附有额外的解释。它要求您手动删除任何重复或不需要的PATH组件。虽然这并不是非常优雅,但通常会更加简单易行。

  1. echo $PATH > path.txt 将当前路径写入文本文件
  2. 编辑path.txt(例如使用nano path.txt
  3. export PATH=$(cat path.txt)将路径设置为文件内容
  4. rm path.txt 删除该文件

注意:所有这些都是针对您当前的会话,在您想要永久更改PATH时,您必须修改您的bash设置文件(例如~/.bashrc)。


3

如果您只想删除任何重复的路径,我会使用我写的这个脚本,因为我之前遇到多个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”以解决此问题,但这将更改路径中所有目录的顺序,我认为这不是一个理想的副作用。 - Tagar

2

% 表示匹配字符串末尾,# 表示匹配字符串开头。 - sabgenton

1

你是如何将这些重复路径添加到你的PATH变量中的?你一定编辑了其中一个 . 文件。(.tcshrc,或.bashrc等,具体取决于你的系统/ shell)。解决方法是再次编辑文件并删除重复路径。

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

请注意,还有一些系统范围的配置文件,但你很少修改它们,因此最有可能更改的是你个人主目录中的文件(如果你想要在确定一组路径后使这些更改永久生效)。


1

对于一个简单的复制粘贴模板,我使用这个Perl代码片段:

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

这样你就不需要为替换运算符转义斜杠。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接