bash - 为什么如果我使用 'echo' 就可以工作,否则就不行?

标签 bash if-statement

所以我目前只是试图遍历我正在调用以下 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/

相关文章:

java - 在 Unix 中编译和运行 java(来自 Windows)

bash - "-"参数之前的 "head"有何作用?

java - 读取非负整数列表并显示最大整数、最小整数以及所有整数的平均值

if-statement - Shiny 的多个 IF if 语句

bash - 检查每行的特定分隔符 - bash

bash - 如何绑定(bind)向上箭头键以转到下一个唯一命令(macOS 终端)?

php - 如果body class hasclass添加js 如果没有添加这个js

C# 在检查条件时表现异常

c# - 验证整数值的最短方法

bash - 如何检查 curl 是否成功并打印消息?