$ PATH中的重复条目有问题吗?


45

我从几个朋友那里得到bashrc。因此,我最终在$ PATH变量中有重复的条目。我不确定这是否是长时间启动命令的问题。$ PATH在bash中如何内部工作?有更多的路径会减慢我的启动时间吗?




Answers:


42

输入更多的条目$PATH并不会直接减慢启动速度,但是每次在shell会话中首次运行特定命令时,它都会减慢速度(并非每次运行命令时都会降低速度,因为bash会保留缓存)。除非您的文件系统特别慢(例如NFS,Samba或其他网络文件系统或Cygwin上的文件系统),否则速度减慢几乎不会被察觉。

当您$PATH目视检查时,重复的条目也有点烦人,您必须多花些功夫。

避免添加重复项很容易。

case ":$PATH:" in
  *":$new_entry:"*) :;; # already there
  *) PATH="$new_entry:$PATH";; # or PATH="$PATH:$new_entry"
esac

旁注:寻找别人的shell脚本意味着执行他编写的代码。换句话说,您可以随时让您的朋友访问您的帐户。

旁注:.bashrc不是设置$PATH或任何其他环境变量的正确位置。环境变量应在中设置~/.profile。见哪个安装文件应当用于在bash设置环境变量?.bashrc和.bash_profile之间的区别


8
+1:不能强调“给予您的朋友访问您的帐户的权限”足够的强调。即使没有危害您的尝试,他们的脚本也可能正是他们所需要的,并且在您获取午餐时仍会吃午餐。
msw

此解决方案的一个可能问题是,如果$ new_entry已经是PATH中的第一个条目,则“:$ new_entry:”不匹配。我通过排除开头的':'冒号来解决此问题。
杰夫·鲍尔

@JeffBauer我看不到问题。我使用case :$PATH:case $PATH,即使条目是第一个还是最后一个也不匹配。
吉尔斯(Gilles)的“所以

31

我见过人们使用awk诸如此类的方法从PATH变量中清除重复项:

PATH=$(printf "%s" "$PATH" | awk -v RS=':' '!a[$1]++ { if (NR > 1) printf RS; printf $1 }')

您可以尝试将其添加到自己的bashrc中,并确保在运行该文件之前在其他位置提供其他文件。

一种替代方法是使用pathmerge实用程序。

至于您的速度问题,这不会显着影响Shell的启动时间,但是可以节省一些时间来完成命令的制表符补全,特别是在路径中找不到命令并且重复搜索相同命令的情况下。寻找它的文件夹。

关于安全性的说明:您应该在这里认真Gilles关于安全性的警告。通过提供另一个用户拥有的文件,您可以免费获得这些用户的权限,以使他们在每次启动Shell时都可以以您的用户身份执行自己的代码。如果您不信任密码的用户,则不应获取其外壳文件。


6
我喜欢awk单行代码,但它会打印结尾的ORS':'。因此,我将其修改为:PATH=$(echo "$PATH" | awk -v RS=':' -v ORS=":" '!a[$1]++{if (NR > 1) printf ORS; printf $a[$1]}')
gkb0986

尾随:不仅是表面上的问题。这与添加.到您的路径相同,这是潜在的危险。
wisbucky

我已经编辑了答案,以包含gkb0986中的修复程序。
蒂姆·莱瑟

@TimLesher我从未编辑过答案的原因是它对我不起作用....,没有它的原始作品也起作用(包括留尾随分隔符。我不知道有什么区别。
迦勒

1
@ gkb0986如果路径包含转义的空间,例如PATH = / bin:/ foo \ bar:/ usr / bin,则此解决方案仍然失败。我在unix.stackexchange.com/a/124517/106102中
maharvey67

13

根据@Gilles答案,您可以将其包装在函数中以最大程度地减少键入:

function addToPATH {
  case ":$PATH:" in
    *":$1:"*) :;; # already there
    *) PATH="$1:$PATH";; # or PATH="$PATH:$1"
  esac
}

addToPATH /Applications/AIRSDK_Compiler/bin
addToPATH ~/.local/lib/npm/bin

1
最实用的答案(也许是高级的)。
ijoseph '18

3

仅执行第一个匹配$PATH项,因此此后不处理任何后续条目。这就是为什么您有时应该修改条目中的顺序$PATH以使您的环境按预期运行的原因。

要回答您的问题:这不应该是启动缓慢的原因。


1
但是,当我键入一个不存在的命令时,它会花费更长的时间。它将在同一文件夹中搜索两次该命令。
巴尔基2011年

@balki您的意思是完成命令TAB?在这种情况下,您应该检查完整的定义是否看起来像complete -c which -a。您应该删除-a参数。您可以检查通过发出命令:complete | grep which
拉吉什2011年

如果在查找之前多次搜索相同目录,则可能仍然是一个问题。
Random832

-1

为了防止在PATH中重复输入,我必须在〜/ .bash_profile和〜/ .bashrc中都放置以下内容:

PATH=$(echo $(sed 's/:/\n/g' <<< $PATH | sort | uniq) | sed -e 's/\s/':'/g')

主要缺点是它对PATH条目进行排序,但是我认为我可以接受。


搜索路径的顺序非常重要。
邵逸夫
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.