bash:将整个命令(带参数)传递给函数

时间:2012-10-15 15:33:11

标签: bash scripting

我本质上是在尝试实现一个断言另一个命令的失败(非零退出代码)的函数,并在失败时打印一条消息。

这是我的功能:

function assert_fail () {
    COMMAND=$@
    if [ `$COMMAND; echo $?` -ne 0 ]; then 
        echo "$COMMAND failed as expected."
    else
        echo "$COMMAND didn't fail"
    fi
}

# This works as expected
assert_fail rm nonexistent

# This works too
assert_fail rm nonexistent nonexistent2

# This one doesn't work
assert_fail rm -f nonexixtent

只要我向命令添加选项,它就不起作用。以下是上述输出:

rm: cannot remove `nonexistent': No such file or directory
rm nonexistent failed as expected.
rm: cannot remove `nonexistent': No such file or directory
rm: cannot remove `nonexistent2': No such file or directory
rm nonexistent nonexistent2 failed as expected.
rm -f nonexistent didn't fail

我试过在命令周围加双引号,但无济于事。我希望上面的第三次调用能够产生与其他两种相似的输出。

我感谢任何/所有帮助!

2 个答案:

答案 0 :(得分:8)

@rici正确地指出了你所看到的问题,但你的包装函数存在一些实际问题。首先,它没有在参数中正确保留空格(以及其他一些有趣的字符)。 COMMAND=$@(或COMMAND="$@")将所有参数合并为一个字符串,从而失去参数与参数内空格之间的区别。要保持直线,请直接使用"$@"而不将其存储在变量中,或将其存储为数组(COMMAND=("$@"),然后将其作为"${COMMAND[@]}"执行)。其次,如果命令将任何内容输出到stdout,它将对您的退出状态检查造成严重破坏;正如@chepner所说,直接测试它。这是我建议的重写:

function assert_fail () {
    if "$@"; then 
        echo "$* didn't fail"
    else
        echo "$* failed as expected."
    fi
}

请注意,我执行echo命令的方式确实失去了参数中空格的区别。如果这是一个问题,请将echo命令替换为:

printf "%q " "$@"
echo "didn't fail"

printf "%q " "$@"
echo "failed as expected."

答案 1 :(得分:5)

rm -f永远不会在不存在的文件上失败。它与你的包装器无关。见man rm

OPTIONS
       -f, --force
              ignore nonexistent files, never prompt