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

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


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

以下问题涉及两个连接器之间的区别,但主要是在评论中:


如何一次性启动两个Ubuntu应用程序?
如何在终端中组合多个命令?

所以这里有一些相关的问题:


;&&有什么区别?

何时分别使用它们?最好能看到一些用例:如果要运行命令然后在关闭计算机后再运行,我应该选择哪个连接器?
它们的优点和危险是什么? Robie Basak在对此答案的评论中提到,例如,如果命令链中的第一个元素失败,则类似cd /somewhere_else; rm -Rf *的命令可能具有破坏性后果。
如果相关,它们来自何处?


评论

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

另请注意,使用set -e运行脚本将在失败时停止脚本,就像所有命令都与&&连接一样。

stackoverflow.com/questions/3573742/…

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

#1 楼

备忘单:

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.


评论


当然,A&B&:在后台运行A,然后在后台运行B(无论是否成功),然后将控制权返回给Shell。这通常与同时运行两个进程大致相同。

–lmat-恢复莫妮卡
2015年10月14日在8:58

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

–user230910
15-10-23在4:29



@ user230910:那应该是(A && B)&。

–leftaround关于
15年12月23日在23:09

您可以为此参考权威文件吗?

–Jaime Hablutzel
16年8月14日在20:27

@JaimeHablutzel在SHELL GRAMMAR下查看man bash->列表

– wjandrea
18年5月6日在3:56



#2 楼

如果第一个命令以状态0退出(成功),则&&仅运行第二个命令。即使第一个命令以非零状态退出,;也会运行这两个命令。

&&的示例可以等同地解释为

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


评论


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

– don.joey
13年8月20日在20:51



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

–乔罗巴
13年8月21日在11:43

#3 楼

使用;将执行命令,而与第一个命令是否成功无关。
只有当第一个命令成功执行(状态0)时,使用&&才会执行第二个命令。
两者的用法不同。就像更长的过程一样,例如对于安装,您需要编译并安装它。您应该make && make install。因此,仅当make成功时,安装才会运行。
对于相关命令,应使用&&
拧bash或带有独立命令的命令,请使用;
因此,如果要关闭计算机,即使第一个作业失败,也请使用;,但是如果要在第一个作业完全成功的情况下启动关机,请使用&&

#4 楼

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

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

关于第四个问题:他们是Bash语法。

使用这两种方法都没有内在的危险。同样,上面的定义就足够了。这意味着如果&&不成功,则会在b产生意想不到的影响时编写a。恕我直言,不需要进一步的规则或解释。

#5 楼


A; B#先执行A,然后执行B,而不管A是否成功

A && B#当且仅当A成功了,才运行B

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

A&#在后台运行A。


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

示例:

-连接两个命令的输出:

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


-进入目录并执行在不更改外壳程序当前目录的情况下从那里执行命令:

(cd target-directory && jar -xf ../my-jar)


#6 楼

杰克的备忘单说得清清楚楚,很赞。但是所有这些事情都有一个更普遍的选择理由。当您在shell中进行操作时,您不必只记住这些事实。有关更多背景信息,您可能还想知道:;通常在C,C ++,Perl,Java,C#,awk,以及从中衍生出的多种语言。它在所有这些功能中都执行相同的功能:先做一件事,然后再做另一件事。就像句子结尾的句点一样。

&在C中用于按位与,因此&&在逻辑AND中使用。从逻辑上说,C语言中的事物具有“捷径”功能。快捷方式意味着对于AND,如果第一件事为假,则没有理由检查第二件事。 AND中的单个错误项表示整个情况将是错误的。在shell中,这意味着如果第一个命令失败,它将不会进入第二个命令。或者,如果第一件事起作用,它将进入第二件事,看看它是否“可能为假”。

|在C中用于按位“或”运算,因此||用于逻辑“或”。逻辑OR也具有快捷键功能。在OR中,这意味着您寻找第一个真实的事物。因此,如果第一件事失败,它将尝试第二件事。


评论


好的答案,谢谢

– don.joey
5月5日20:54