所以我目前只是试图遍历我正在调用以下 bash 脚本的当前目录,每次找到一个时都会打印“我们找到了一个 .c 文件”。我有一个 if 语句来检查 args,因为我将扩展脚本,如果没有找到 args,它无论如何都会运行,并且一个 arg 会告诉脚本要查找的目录。
问题是,这段代码不起作用:
if [ -z "$#" ]
then
for i in *.c; do
echo "We found a .c file"
done
fi
但是,如果我在其中添加 echo "Test"
,它会起作用吗?
if [ -z "$#" ]
echo "Test"
then
for i in *.c; do
echo "We found a .c file"
done
fi
我是 bash 的新手,不知道为什么会这样。谁能帮帮我?
最佳答案
$#
,它报告参数个数,绝不是空字符串 - 如果您不指定参数,$#
评估为 0
,它仍然是一个非空字符串(-z
测试空 字符串)。
因此, [ -z "$#" ]
总是(逻辑上)为假。
您正在寻找的 - 使用惯用的 Bash - 是:
if [[ $# -eq 0 ]]; then ... # -eq compares *numerically*
作为anishsane在评论中指出,符合 POSIX 的 [ $# -eq 0 ]
也会在这里工作;不过,一般来说 - 除非你明确表示要编写符合 POSIX 标准的 shell 代码 - 你最好坚持使用 more predictable, more feature-rich (and marginally faster) Bash-specific constructs .
或者,使用 arithmetic evaluation :
if (( $# == 0 )); then ...
至于为什么你的第二个片段导致了if
要输入的分支:
你的错位 echo "Test"
- 由于放置在 then
之前关键字,导致 echo
命令被解释为条件的一部分。
换句话说:评估的条件是有效的
[ -z "$#" ]; echo "Test"
,一个包含(两个)命令的列表,其中最后一个命令的退出代码决定了条件的结果。
自 echo
总是成功(退出代码0
)[1]
,条件作为一个整体评估为(逻辑)真,if
分支已进入。
[1] gniourf_gniourf在评论中指出您可以制作一个简单的echo
命令失败(退出代码为 1
),如果您对无效的源/目标使用输入/输出重定向;例如,echo 'fail' > /dev/full
.
(请注意,如果重定向源/目标从根本上无效 - 一个不存在的输入文件或无法创建/打开的输出文件(相对于可以打开的输出目标)具有写入权限但最终不能写入,例如 Linux 上的 /dev/full
)- Bash 甚至从不调用手头的命令,因为它在遇到无效重定向时“放弃”:
{ echo here >&2; echo hi; } >/dev/full # Linux: 'here' still prints (to stderr)
{ echo here >&2; echo hi; } >'' # invalid target: commands are never invoked
)
关于bash - 为什么如果我使用 'echo' 就可以工作,否则就不行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37825265/