【发布时间】:2019-11-25 14:06:10
【问题描述】:
我遇到了tar 的问题,在涉及已安装 Windows docker 卷上的时间戳的情况下(长话短说),我决定尝试pax。它起作用了,但我希望脚本像以前一样在旧机器上工作,直到我到处安装pax。我的命令如下所示:
tar -czf foo.tar.gz foo || echo "didnt work, trying pax" && echo foo | pax -wz > foo.tar.gz
意图是pax 仅在tar 失败时运行。但是在没有pax 的机器上运行它会出现pax 不存在的意外错误。出乎意料,因为我认为如果前面的命令返回成功,|| 会丢弃右边的任何内容。把它缩小到一个合适的测试用例我已经得到了这个,用bash和dash测试:
# as expected, fails trying to run missing command
echo hello && false || echo 'trying different command' && dsadsa
# hello
# trying different command
# bash: dsadsa: command not found
# UNEXPECTED, command is never run but nevertheless fails because it's missing
echo hello && true || echo 'trying different command' && dsadsa
# hello
# bash: dsadsa: command not found
# as expected, does not try run missing command, current solution/workaround
echo hello && true || (echo 'trying different command' && dsadsa)
# hello
为什么会这样?以及如何将 sub-shelling 用作解决方法?
【问题讨论】:
-
a && b || c不等同于if a; then b; else c; fi。如果a或b失败,c将运行。 -
一般规则:不要将
&&和||混合在同一个链中(它们的优先级也相同,与其他语言中的布尔值&和|不同)。如果这是您的意思,请使用if声明。 -
@chepner 我的理解是它们应该从左到右阅读,因为它们具有相同的优先级。
if-then-else是个好主意,谢谢 -
@chepner 知道了,应该读作
(a && b) || c,而不是a && (b || c)。现在一切都说得通了。 -
顺便说一句,如果您的唯一目的是分组,请使用
a && { b || c; },而不是a && (b || c);这样,当您实际上不需要它时,我们就可以避免 subshell 开销。