这个命令在 bash 中是什么意思

what does this command mean in bash

我遇到了一个 bash 脚本,其中包含以下命令:

cd .git/hooks
[ `eval ls -l | grep -io 'Post-Commit' | wc -l` -eq 1 ] && echo 'post-commit file check... Pass' || echo 'post-commit file check... Fail'

我认为是要检查 .git/hooks 文件夹中名为 post-commit 的文件。但即使我在目录中创建文件 post-commit,我得到的输出为:post-commit file check... Fail.

我是不是做错了什么? 我使用以下方法创建我的文件:

cat > post-commit

然后我写入它并使用 chmod +x post-commit

将其变成可执行文件

任何帮助将不胜感激

虽然这个脚本似乎是针对 Git 钩子,但它在任何方面都不依赖于Git,所以我放弃了 and tags. It also has nothing to do with Linux so I dropped the 标签。

这里的eval完全没有必要1可以去掉:

[ `ls -l | grep -io 'Post-Commit' | wc -l` -eq 1 ] &&
  echo 'post-commit file check... Pass' ||
  echo 'post-commit file check... Fail'

(为了便于阅读,我将其分成更多行)。

一样,[名义上是一个外部命令。实际上,它实际上内置于大多数 shell 中,包括 bash,因此没有 fork-and-exec。

然而,反引号部分确实需要 fork-and-exec。 `command` 形式的文本或多或少等同于 $(command) 形式的代码。 $(...) 形式通常更优越,因为它提供了合理的嵌套,因此如果可以选择使用哪种形式,通常应该更喜欢 $(...) 形式。在任何情况下,它仅表示:运行 显示的命令并在此处插入其输出。所以我们要 运行:

ls -l | grep -io 'Post-Commit' | wc -l

作为.

ls -l 的作用显而易见:列表很长。

grep -io有两个标志:-i,意思是忽略大小写,和-o,意思是只显示匹配的部分作为输出。因此,这将查找 ls -l 输出,其中该行包含 POST-COMMITpost-commitpOSt-COMmit 等。

wc -l 的作用显而易见:计算行数。

最终结果是我们统计了文件名中有这个字符串的文件数。例如,一个名为 this-GETS-RUN-post-COMMIThaste-er 的文件被计算在内。

将此计数的最终结果与 1 进行数字相等性比较。如果数字一,子句的&&部分就是运行;如果不是,|| 部分是 运行.

总的来说,这个脚本没有做任何有用的事情,因为它太草率了。它允许大小写混合的文件名; Git 没有。 (但是,在 OS 允许不区分大小写的文件名匹配的文件系统上,Git 使用严格小写导致访问混合大小写或毕竟是大写名称。)如果我们找到两个或更多匹配的文件,它会抱怨,但是名称仅具有 sub 匹配的文件在这里可能不是问题。


1shell 命令中的 eval 使 shell 首先进行各种扩展, 然后 运行 命令。在它有用的地方——例如 eval $cmd——它通常也很危险:你必须对 $cmd 中的内容进行极其严格的控制。在没有扩展的情况下,就像在这种情况下一样,它是无用的。尽量避免。