这个命令在 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,所以我放弃了git and githooks tags. It also has nothing to do with Linux so I dropped the 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'
(为了便于阅读,我将其分成更多行)。
与一样,[
名义上是一个外部命令。实际上,它实际上内置于大多数 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-COMMIT
、post-commit
、pOSt-COMmit
等。
wc -l
的作用显而易见:计算行数。
最终结果是我们统计了文件名中有这个字符串的文件数。例如,一个名为 this-GETS-RUN-post-COMMIThaste-er
的文件被计算在内。
将此计数的最终结果与 1
进行数字相等性比较。如果数字是一,子句的&&
部分就是运行;如果不是,||
部分是 运行.
总的来说,这个脚本没有做任何有用的事情,因为它太草率了。它允许大小写混合的文件名; Git 没有。 (但是,在 OS 允许不区分大小写的文件名匹配的文件系统上,Git 使用严格小写导致访问混合大小写或毕竟是大写名称。)如果我们找到两个或更多匹配的文件,它会抱怨,但是名称仅具有 sub 匹配的文件在这里可能不是问题。
1shell 命令中的 eval
使 shell 首先进行各种扩展, 然后 运行 命令。在它有用的地方——例如 eval $cmd
——它通常也很危险:你必须对 $cmd
中的内容进行极其严格的控制。在没有扩展的情况下,就像在这种情况下一样,它是无用的。尽量避免。
我遇到了一个 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 and githooks tags. It also has nothing to do with Linux so I dropped the 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'
(为了便于阅读,我将其分成更多行)。
与[
名义上是一个外部命令。实际上,它实际上内置于大多数 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-COMMIT
、post-commit
、pOSt-COMmit
等。
wc -l
的作用显而易见:计算行数。
最终结果是我们统计了文件名中有这个字符串的文件数。例如,一个名为 this-GETS-RUN-post-COMMIThaste-er
的文件被计算在内。
将此计数的最终结果与 1
进行数字相等性比较。如果数字是一,子句的&&
部分就是运行;如果不是,||
部分是 运行.
总的来说,这个脚本没有做任何有用的事情,因为它太草率了。它允许大小写混合的文件名; Git 没有。 (但是,在 OS 允许不区分大小写的文件名匹配的文件系统上,Git 使用严格小写导致访问混合大小写或毕竟是大写名称。)如果我们找到两个或更多匹配的文件,它会抱怨,但是名称仅具有 sub 匹配的文件在这里可能不是问题。
1shell 命令中的 eval
使 shell 首先进行各种扩展, 然后 运行 命令。在它有用的地方——例如 eval $cmd
——它通常也很危险:你必须对 $cmd
中的内容进行极其严格的控制。在没有扩展的情况下,就像在这种情况下一样,它是无用的。尽量避免。