当尝试使用名称中的斜杠检查命令的存在时,Bash的'hash'命令总是成功

时间:2017-02-21 07:55:14

标签: bash

考虑以下脚本:

#!/bin/bash
hash ./a.sh  && echo ./a.sh exists
hash foo     && echo foo exists
hash bar/foo && echo bar/foo exists
bar/foo

它尝试检查是否存在不同的命令,即./a.shfoobar/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效果更好,但我认为它们大多是同义词。

1 个答案:

答案 0 :(得分:1)

请参阅bash' documentation on how commands are looked up and executed

  

3.7.2命令搜索和执行

     

将命令拆分为单词后,如果结果很简单   命令和可选的参数列表,以下操作是   服用。

     
      
  1. 如果命令名称不包含斜杠,则shell会尝试找到它 。如果存在该名称的shell函数,那么   函数按Shell函数中的描述调用。
  2.   
  3. 如果名称与函数不匹配,shell将在shell builtins列表中搜索它。如果找到匹配,那就是内置的   调用。
  4.   
  5. 如果名称既不是shell函数也不是内置函数,并且不包含斜杠,则Bash会搜索的每个元素 $PATH    表示包含该名称的可执行文件的目录。 Bash使用哈希表来记住可执行文件的完整路径名   避免多次 PATH 搜索(请参阅的说明   Bourne Shell Builtins中的 hash )。只有在命令为的情况下,才会对 $PATH 中的目录进行完整搜索   在哈希表中找不到 。如果搜索不成功,则   shell搜索名为的已定义shell函数   command_not_found_handle。如果该函数存在,则调用它   使用原始命令和原始命令的参数作为其   参数,函数的退出状态成为退出状态   贝壳。如果未定义该函数,则shell会输出错误   消息并返回退出状态127。
  6.   
  7. 如果搜索成功, 或命令名称包含一个或多个斜杠 ,则shell会单独执行指定的程序   执行环境。 ...
  8.   

简而言之,仅对不包含斜杠的命令执行查找和散列。如果命令看起来像路径(即包含斜杠),则假定它在该路径上引用可执行文件,并且不需要复杂的查找过程。因此,hash使用斜杠处理参数,就好像它们会自行解析并以无条件退出成功状态(即不检查指定文件是否实际存在且可执行)。