我本质上是在尝试实现一个断言另一个命令的失败(非零退出代码)的函数,并在失败时打印一条消息。
这是我的功能:
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
我试过在命令周围加双引号,但无济于事。我希望上面的第三次调用能够产生与其他两种相似的输出。
我感谢任何/所有帮助!
答案 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