这个命令在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,所以我删除了Git和githooks标签。它也与Linux无关,所以我放弃了Linux标签。

这里的eval完全没有必要1我们可以放弃它:

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

(为了可读性,我把它分成了更多行(。

正如Losko在评论中指出的那样,[名义上是一个外部命令。在实践中,它实际上内置在大多数shell中,包括bash,因此没有fork和exec。

然而,后引号部分确实需要一个fork和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中的内容进行极其严格的控制。在没有扩展的地方,就像在这种情况下,它是无用的。尽量避免。

最新更新