考虑以下脚本:
#!/bin/bash
hash ./a.sh && echo ./a.sh exists
hash foo && echo foo exists
hash bar/foo && echo bar/foo exists
bar/foo
它尝试检查是否存在不同的命令,即./a.sh
,foo
和bar/foo
(例如foo
目录中的bar
可执行文件。然后,它尝试运行bar/foo
命令。我的输出是:
./a.sh exists
./a.sh: line 3: hash: foo: not found
bar/foo exists
./a.sh: line 5: bar/foo: No such file or directory
预计前两行,以及最后一行。但是,第三行表示hash
的{{1}}命令没有失败,这很奇怪。
我认为使用“hash”更适合测试脚本即将使用的命令的存在。至少,它在this SO answer中被提及为可能的替代方案。事实证明,对于相对路径的命令(未使用绝对路径进行测试),它不能很好地工作。这是为什么? bar/foo
效果更好,但我认为它们大多是同义词。
答案 0 :(得分:1)
请参阅bash' documentation on how commands are looked up and executed:
3.7.2命令搜索和执行
将命令拆分为单词后,如果结果很简单 命令和可选的参数列表,以下操作是 服用。
- 如果命令名称不包含斜杠,则shell会尝试找到它 。如果存在该名称的shell函数,那么 函数按Shell函数中的描述调用。
- 如果名称与函数不匹配,shell将在shell builtins列表中搜索它。如果找到匹配,那就是内置的 调用。
- 如果名称既不是shell函数也不是内置函数,并且不包含斜杠,则Bash会搜索的每个元素
$PATH
表示包含该名称的可执行文件的目录。 Bash使用哈希表来记住可执行文件的完整路径名 避免多次PATH
搜索(请参阅的说明 Bourne Shell Builtins中的hash
)。只有在命令为的情况下,才会对$PATH
中的目录进行完整搜索 在哈希表中找不到 。如果搜索不成功,则 shell搜索名为的已定义shell函数command_not_found_handle
。如果该函数存在,则调用它 使用原始命令和原始命令的参数作为其 参数,函数的退出状态成为退出状态 贝壳。如果未定义该函数,则shell会输出错误 消息并返回退出状态127。- 如果搜索成功, 或命令名称包含一个或多个斜杠 ,则shell会单独执行指定的程序 执行环境。 ...
醇>
简而言之,仅对不包含斜杠的命令执行查找和散列。如果命令看起来像路径(即包含斜杠),则假定它在该路径上引用可执行文件,并且不需要复杂的查找过程。因此,hash
使用斜杠处理参数,就好像它们会自行解析并以无条件退出成功状态(即不检查指定文件是否实际存在且可执行)。