哪个更好:使用; 或&&在一行中执行多个命令?


427

在教程和操作方法中,我经常看到命令组合。例如,

sudo apt-get update && sudo apt-get install pyrenamer

似乎有四种可能的连接器:&&&||;。尽管& 连接器对我来说很清楚(它会将进程发送到后台并使终端可用),但尚不清楚&&和之间的区别;||直到Kaya发表评论,我才知道。

下列问题处理两个连接器之间的差异,但主要是在注释中进行:

因此,这里有一些相关的问题:

  1. ;和之间有什么区别&&
  2. 什么时候应该分别使用它们?很高兴看到一些用例:如果我要运行命令,然后在关闭计算机后运行,我应该选择哪个连接器?
  3. 它们的优点危险是什么?Robie Basak在对此答案的评论中提到,例如,cd /somewhere_else; rm -Rf *如果命令链中的第一个元素失败,则类似的命令可能会造成破坏性后果。
  4. 如果相关,它们来自哪里?

7
还有一个您可能没有遇到过的连接器:与其他连接器||相同,&&只是它仅在第一个命令以非零(不成功)状态退出时才执行第二个命令。
卡亚

4
另请注意,使用来运行脚本set -e会在失败时停止脚本,就好像所有命令都已连接一样&&
choroba


3
没有人回答Qn 4 ...我怀疑&&和||的行为 受到C编程语言的启发。在(x && y)的情况下,如果x的计算结果为false,则整个表达式都必须为false,以便编译器可以优化y的计算,以防代价高昂。现代的C和C ++标准实际上需要此优化,因此程序可以安全地假设,如果x为假,则不会评估y。例如,即使ptr为null,(ptr && ptr-> days> 31)也不会崩溃。同样在C中,语句以;结尾。不管同一行上是否有其他语句。
凯文

Answers:


771

备忘单:

A; B    # Run A and then B, regardless of success of A
A && B  # Run B if and only if A succeeded
A || B  # Run B if and only if A failed
A &     # Run A in background.

19
当然,请执行以下操作A & B &:在后台运行A,然后在后台运行B(无论是否成功),然后将控制权返回给Shell。这通常与同时运行两个进程大致相同。
有限赎罪2015年

4
是否可以说:在后台运行a,然后仅在工作正常的情况下在后台运行b?(我猜&&&?)
user230910 2015年

14
@ user230910:应该是(A && B) &
大约

5
您可以为此参考权威文件吗?
Jaime Hablutzel 2016年

@Jack从Cronjob执行时,它不太遵循这个规则,为什么?对于python文件
CodeGuru

77

&&仅当第一个命令以状态0退出(成功)时,才运行第二个命令。;即使第一个命令以非零状态退出,也要运行这两个命令。

您的示例&&可以等效地解释为

if sudo apt-get update ; then
    sudo apt-get install pyrenamer
fi

谢谢。我已经更新了问题,以确保可以轻松地区分不同的子问题。
don.joey

5
@Private:;如果第二个命令不需要上一个命令就可以成功使用。
choroba

31

使用;将执行命令,而不管第一个命令是否成功。

&&仅当第一个命令成功执行(状态0)时,才使用execute 2nd命令。

两者都以不同的角度使用。就像更长的过程一样,例如对于安装,您需要编译并安装它。你应该make && make install。因此,安装将仅在make成功的情况下运行。

因此,对于相关命令,应使用 &&

拧bash或使用具有独立命令的命令 ;

因此,如果您要关闭计算机,甚至第一个作业都无法使用;,但是如果您希望第一个作业完全成功,请启动关机使用&&


14

a ; b无论a的退出状态如何,都将运行b。a && b仅在成功的情况下运行b。

这对于回答前三个问题是必要且充分的。特别是,2的范围太广,不能给出“一个”确定的答案-最好的选择是根据具体情况决定。

至于第四个问题:它们是Bash语法

两者都不存在内在的危险。同样,上面的定义就足够了。这意味着如果没有成功,您将&&在什么时候b产生意想不到的效果时进行写作a。恕我直言,不需要进一步的规则或解释。


1

一种; B#先执行A然后执行B,无论A是否成功

A && B#仅在A成功的情况下运行B

A || B#仅当A失败时运行B

A&#在后台运行A。

很好的经验法则。我要补充一点,在某些情况下,当我们希望将它们视为单个单元,或者不想将某些操作结果与当前外壳结合在一起时,在子外壳中使用这些命令很有意义。

例子:

-连接两个命令的输出:

(ls foo; ls bar) > single-result.txt

-进入目录并从那里执行命令,同时不更改shell的当前目录:

(cd target-directory && jar -xf ../my-jar)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.