为什么“which”会给出错误的结果?

为什么“which”会给出错误的结果?

我在 Ubuntu 12.04 shell 上执行以下命令:

sudo bash -c "echo $PATH; which python"

显示类似

/home/me/env/develop/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
/usr/bin/python

以及以下命令

ls /home/me/env/develop/bin

显示(以及其他)

python

根据man页面,该which命令会在 中定义的所有路径中查找给定的可执行文件PATH。该man页面没有严格指定搜索的“顺序”,但通常从环境变量的开头到结尾PATH

现在,路径/home/me/env/develop/bin包含一个python可执行文件(模式设置正确,而不是符号链接),这也是中的第一个路径PATH。但which命令显示的位置完全不同!

这是为什么?我是不是在做蠢事?这跟魔法有关吗sudo?这是 bug 吗?

答案1

这不是一个错误。$PATH双引号内的内容在 shellbash -c看到它之前就被扩展了。

这意味着你实际上会运行:

sudo bash -c "echo /home/me/env/develop/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games; which python"

小测试:

$ foo="hello"
$ sudo bash -c "echo $foo"
hello

要找到问题的根源,请运行:

sudo bash -c 'echo $PATH; which python'

这以前不会扩大$PATH

解决路径问题的一个方法是将路径设置为.bashrc而不是.bash_profile— — 如果我没记错的话,您的路径设置在那里 — — 这样即使对于非登录 shell 也会加载它(如bash -c)。或者您运行bash -lc以让它运行登录 shell,这将加载.bash_profile

相关内容