为什么“键入哪个”表示“哪个是散列的”?


31

如果是shell-builtins(例如type本身):

$ type type
type is a shell builtin

$ which type
<Doesn't return anything since it's a shell builtin, silently exits>

如果是命令(通常)(例如python):

$ type python
python is /usr/bin/python

$ which python
/usr/bin/python

如果是which(位于的命令/usr/bin/which

$ type which
which is hashed (/usr/bin/which)
$ which which
/usr/bin/which

为什么type which这么说呢which is hashedwhich散列的意义是什么?它的实际含义是什么?

Answers:


40

您可能设置了很长的PATH,并且要找到可执行文件,shell需要搜索路径。为了避免每次您要运行程序时耗时的过程,shell可能会保留已找到的程序列表。该列表称为“哈希”。当shell说它which被散列时,意味着它已经完成了PATH搜索,which并在散列中找到并保存了它的位置。

man bash 解释如下:

Bash使用哈希表来记住可执行文件的完整路径名(请参见下面的SHELL BUILTIN COMMANDS下的hash)。仅当在哈希表中找不到命令时,才对PATH中的目录进行完全搜索。

虽然散列通常可以加快Shell操作的速度,但在一种情况下,它会引起问题。如果更新系统,结果某些可执行文件移至新位置,则外壳可能会感到困惑。解决方案是运行hash -r,这会使外壳程序忘记所有散列的位置并从头开始搜索PATH。

为什么哈希中缺少某些可执行文件?

至少执行一次后,可执行文件才会放入哈希中。观察:

$ type python
python is /usr/bin/python
$ python --version
Python 2.7.3
$ type python
python is hashed (/usr/bin/python)

python 仅在执行后才进行哈希处理。

如何检查bash哈希中的内容

哈希的内容在bash数组中可用BASH_CMDS。您可以使用命令查看其中的内容declare -p BASH_CMDS。当打开新的外壳程序或子外壳程序时,哈希为空。使用命令时,命令会一一添加。在新打开的外壳中,观察:

$ declare -p BASH_CMDS
declare -A BASH_CMDS='()'
$ which which
/bin/which
$ declare -p BASH_CMDS
declare -A BASH_CMDS='([which]="/bin/which" )'
$ python --version
Python 2.7.3
$ declare -p BASH_CMDS
declare -A BASH_CMDS='([which]="/bin/which" [python]="/usr/bin/python" )'

+1,很好的解释。但是为什么which不这样做python呢?
jobin 2014年

@Jobin请参阅更新的答案。
2014年

2
看起来哈希一直持续到我们不退出shell为止。一旦重新启动终端,就不会说命令已被哈希处理。
Aditya 2014年

1
@Aditya是的。我在答案中添加了关于此内容的部分。
2014年

hash -l会比使用起来容易declare -p BASH_CMDS
phuclv
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.