在Shell命令中,“&&”的目的是什么?

475
据我所知,在命令后添加&是为了在后台运行该命令。 &使用示例:tar -czf file.tar.gz dirname & 那么&&又是什么意思呢?(参考示例
10个回答

534
此外,您还有 ||,它是逻辑或,并且还有分隔符;,它只是一个分隔符,不关心命令之前发生了什么。
$ false || echo "Oops, fail"
Oops, fail

$ true || echo "Will not be printed"
$  

$ true && echo "Things went well"
Things went well

$ false && echo "Will not be printed"
$

$ false ; echo "This will always run"
This will always run

有关此内容的一些详细信息可以在Bash手册的命令列表中找到。


4
还有这个“技巧”。 Command && echo "命令执行成功" || echo "命令执行失败" - Dan
8
@Dan 这是一个不好的技巧。只有在您可以保证 && 后面的命令成功执行时,它才能按预期工作。使用 if command; then command; else command; fi 不会明显增加长度,并且始终能按预期工作。 - chepner

491
< p >< code >&& 使您能够根据前一个命令是否成功完成而执行某些操作 - 这就是为什么它通常被链接为do_something && do_something_else_that_depended_on_something的原因。


167

命令行 - && 的目的是什么?

在 shell 中,当你看到

$ command one && command two

意图是只有在第一个命令成功执行后,才会执行紧随其后的&&命令。这是Posix shell的惯用法,不仅适用于Bash。

它旨在防止第一个进程失败时运行第二个进程。

你可能会注意到我使用了“意图”这个词——这是有好的原因的。并非所有程序都具有相同的行为,因此要使其正常工作,您需要通过阅读文档和必要时查看源代码来了解程序如何处理“失败”情况。

您的shell将返回值为0视为true,其他正数视为false

程序在退出时返回信号。如果它们成功退出,则应返回0,否则应返回大于零的值。这允许进程之间进行有限的通信。

posix shell grammar中,&&被称为AND_IF,它是命令and_or列表的一部分,其中还包括||,它是具有类似语义的OR_IF
摘自文档的语法符号:
%token  AND_IF    OR_IF    DSEMI
/*      '&&'      '||'     ';;'    */

以下是语法(也引用自文档),它显示任意数量的 AND_IF&&)和/或 OR_IF||)可以链接在一起(因为 and_or 是递归定义的):

and_or           :                         pipeline
                 | and_or AND_IF linebreak pipeline
                 | and_or OR_IF  linebreak pipeline

这两个运算符的优先级相同,且从左到右计算(它们是左结合的)。如文档所述:

An AND-OR list is a sequence of one or more pipelines separated by the operators "&&" and "||" .

A list is a sequence of one or more AND-OR lists separated by the operators ';' and '&' and optionally terminated by ';', '&', or .

The operators "&&" and "||" shall have equal precedence and shall be evaluated with left associativity. For example, both of the following commands write solely bar to standard output:

$ false && echo foo || echo bar
$ true || echo foo && echo bar
  1. In the first case, the false is a command that exits with the status of 1

    $ false
    $ echo $?
    1
    

    which means echo foo does not run (i.e., shortcircuiting echo foo). Then the command echo bar is executed.

  2. In the second case, true exits with a code of 0

    $ true
    $ echo $?
    0
    

    and therefore echo foo is not executed, then echo bar is executed.


33

'&&'被广泛用于使用autotools编译软件。例如:

./configure --prefix=/usr && make && sudo make install

基本上,如果配置成功,则运行make编译,如果编译成功,则以root身份运行make安装程序。我在大多数情况下使用这个方法是因为我相信事情会顺利进行,它让我能够做其他重要的事情,比如查看stackoverflow, 而不需要“监视”进度。

有时候我真的会过分沉迷...

tar xf package.tar.gz && ( cd package; ./configure && make && sudo make install ) && rm package -rf

当我制作一个“从头开始构建Linux”的系统时,我会这样做。


2
在REPL中很好,但对于脚本,我更喜欢在Bash中使用set -o errexit - Franklin Yu
请注意,当使用“&&”时,“set -o errexit”(与“set -e”相同)可能无法按预期工作。请参阅“man set”:在“AND-OR列表”中,根据手册,它将忽略除最后一个命令以外的任何内容,因此,如果您希望它在此类列表中的第一个失败时停止整个脚本,则不会这样做。 - pzkpfw

24

&&可以将多个字符串命令连接在一起,只有前面的命令成功执行后,才会继续执行后续的命令。

同样地,||则是在前一个命令失败时,才会继续执行后面的命令。

请参考Bash Shell Programming


关于“允许连续命令”的问题:但这不是要传播错误/退出代码吗? - Peter Mortensen

12

如果第一条语句成功结束,就执行第二条语句。就像一个if语句:

 if (1 == 1 && 2 == 2)
   echo "test;"

它首先尝试判断1是否等于1。如果是真的,它再检查2是否等于2。


1
有人能解释一下为什么这个问题被用户贬低了吗? - ajspencer
1
@user3243242,这并不是错误的,只是一个不太好的例子来说明&&的用法。 - dan
这是一个关于bash中if测试如何工作的深刻见解。我从未像一系列比较命令一样考虑过它,当任何一个失败时就会中断。所以你得到了我的赞同 :) - PiRK
1
结果是你可以通过使用 || 进行命令链接,直到其中一个成功为止,从而获得相反的行为:eei || leu || uie || echo prout3 || echo "永远不会被执行" - PiRK

9

看下面的例子:

mkdir test && echo "Something" > test/file

Shell会尝试创建目录test,然后只有在成功创建目录后才会尝试在其中创建文件。

因此,如果其中一个步骤失败,您可以中断一系列步骤。


7

command_1 && command_2:只有在成功执行command_1时才会执行command_2。

command_1 || command_2:只有在未成功执行command_1时才会执行command_2。

与主流编程语言中的“if”条件执行类似,例如在if (condition_1 && condition_2){...}中,如果condition_1为false,则会省略condition_2;而在if (condition_1 || condition_2){...}中,如果condition_1为true,则会省略condition_2。 看,这就是你在编码中使用的相同技巧 :)


我不知道你所说的“完全相反”是什么意思,但是$echo '1' || echo '2'只会输出'1'。而$wrong_command || echo '2'则会在下一行打印错误信息和'2'。你能否详细解释一下你认为这里有什么问题? - Xiaonin Li

1
####################### && or (Logical AND) ######################
first_command="1"
two_command="2"

if [[ ($first_command == 1) && ($two_command == 2)]];then
 echo "Equal"
fi

当程序检查命令时,程序会创建一个名为退出代码的数字,如果两个条件都为真,则退出代码为零(0),否则退出代码为正数。只有在显示等于时,如果退出代码产生了零(0),那么这意味着两个条件都为真。

1
欢迎来到stackoverflow。在发布代码片段之前,请确保它能够正常运行。你需要更正它,if [[ ($first_command == "1") && ($two_command == "2") ]];then echo "Equal"; fi - Zheng Qu

0
感谢以上所有人的帮助,你们帮我解决了如何返回与grep匹配的文件的第一行(在我的情况下,第一行包含文件来源的URL)。
for var in sources/* ; do grep -iw "keyword" $var && head -n 1 $_; done

很遗憾,我无法找到不使用for循环的方法来完成这个任务,这可能会限制可扩展性。我有大约1000个文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接