以下链接命令方法之间有什么区别?

cmd1; cmd2
cmd1 && cmd2


#1 楼

假设存在command1 && command2。在这种情况下,仅当command2返回零退出状态时,才会执行command1

;只是命令分隔符。因此,无论返回的command2为何,都将执行command1

$> [[ "a" = "b" ]] && echo ok 

$> [[ "a" = "b" ]]; echo ok 
ok


评论


同样,command1 ||仅当command1返回非零退出状态时,才能使用command2运行command2。

– hammar
2012年4月22日20:19在

请注意,完整表达式的返回值是最后执行的命令的返回值。

–StéphaneGimenez
2012年4月22日在22:05



实际上很奇怪..如果command1返回零,那么执行command2吗?考虑到惰性计算,&&甚至在第一个参数已经为0时也不应查看第二个参数-无论如何结果将为0。

–科尼拉克
2012年4月24日在8:57

@Konerak:对于退出代码,0表示成功,而其他则为假,则为true,因此与“普通”布尔值相比,它有点相反。

– hammar
2012年4月27日在20:25

@hammar似乎很不幸。更为合理的选择是0 ||。 next_step表示上一步的成功,符合逻辑或的惰性评估。

–江强
17-10-17在17:28

#2 楼

cmd1; cmd2执行cmd1,然后执行cmd2,无论如何。它完全等效于将cmd1cmd2放在单独的行上¹。该复合命令的返回状态为cmd2

cmd1 && cmd2执行cmd1。然后,如果cmd1的退出状态为零,则执行cmd2。此复合命令的返回状态为cmd1(如果它不为零)(因此cmd2未运行),否则为cmd2(如果已运行)。返回页首if cmd1; then cmd2; ficmd1 && cmd2等效。主要区别在于,如果if返回非零状态,则带有cmd1的版本将返回0。

命令返回0表示成功,并且返回非零错误代码(介于1和255之间,通常介于1和125之间)因为较高的值具有其他含义)表示失败。因此,cmd1; cmd2的意思是“无论如何都按顺序执行这些命令”,而cmd1 && cmd2的意思是“执行这些命令,但是如果第一个命令失败,则立即停止。”

您可以告诉Shell输入“ exit on错误”模式,方法是运行set -e。在这种模式下,除了条件构造(&&||的左侧,ifwhile的条件部分)外,任何命令返回非零状态后,shell都会退出。因此,在set -e下,;(或换行符)实际上等效于&&²。

¹就控制流而言,即。换行和分号的执行方式完全相同,但它们的解析方式却不完全相同,例如alias ls=true; ls执行ls而不执行true,因为解析器在执行别名定义之前先对ls执行别名解析。
¹这并不是说如果添加了&&,就可以用;盲目替换set -e。例如,;的优先级低于&&,因此cmd1 && cmd2 || cmd3等同于set -e; { cmd1; cmd2; } || cmd3。另外,set -e与子外壳之间的交互很差-详细信息会使该答案偏离的太远了。

评论


“因为更高的值具有其他含义”是什么意思?如果我在编写自己的程序,是否有任何标准的错误命名(编号?)约定?

– rahmu
2012年4月23日在9:42

@rahmu Shell使用错误代码126和127指示根本无法启动该程序,并使用128 + N指示该程序以信号N终止。因此,从Shell出发,唯一清楚地显示该程序的状态代码跑到完成是0到126(如果确实要使读者感到困惑,则为128)。

–吉尔斯'所以-不再是邪恶的'
2012年4月23日在17:02

@吉尔斯:我完全不同意最后一句话。试试echo $(set -e; {false;(exit 2)} && true; echo $?)vs echo $$(set -e; {false &&(exit 2)} && true; echo $?);)

–StéphaneGimenez
2012年4月23日在18:59



@StéphaneGimenez好的,是的,将-e和subshel​​l一起设置可能很时髦。

–吉尔斯'所以-不再是邪恶的'
2012年4月23日20:02在

注意:cmd1; cmd2不一定与cmd1 cmd2相同。想到的情况是cmd1会影响shell解析,例如别名命令或更改本地化设置的命令。例如,别名foo = bar; foo不必与别名foo = bar foo相同。

–StéphaneChazelas
17年1月11日在10:26



#3 楼

无论第一行是否成功,第一行都会一个接一个地执行命令。第二行是shell逻辑的示例:仅在第一个命令成功的情况下才执行第二个命令。这是因为&&是逻辑and。因此,如果第一个命令失败,则已知整行的逻辑状态为假,因此无需评估第二个命令。

#4 楼

更实际的是,

cd /backup/old; rm -rf -- *



cd /backup/old && rm -rf -- *


之间是有区别的。除了这是一种愚蠢的方法外,第一个将删除整个文件系统(或$ HOME,取决于其调用方式),因为无论rm是否成功,它都会运行cd

评论


虽然您的答案是正确的,但是如果用户运行它来亲自查看差异,则很危险。为什么不“回声某事”呢?

–兰迪·斯蒂格鲍尔(Randy Stegbauer)
2012年4月23日在17:46

我相信人们不要做明显的愚蠢的事情。这是我直接听到的+/-示例。

–Reactormonk
2012年4月23日在22:56

@RandyStegbauer因为执行此操作的人员不应该在其文件系统中拥有文件。

– alexg
14-10-15在8:59