用于链接命令的分号或双与号?

Mic*_*ers 1 command-line bash scripts

在编写 bash 脚本时,哪个更好地链接命令、分号;或双与号&&

Eli*_*gan 9

正如steeldriver 所说,两者都不比另一个好。您将它们用于不同的目的。

使用;,如果你想运行一个命令,然后另一个。无论第一个命令是否成功,第二个命令都会运行。用 a 分隔命令与;运行一个命令,然后运行另一个命令的目标相同。在脚本中,这些实现了相同的目标:

first-command
second-command
Run Code Online (Sandbox Code Playgroud)
first-command; second-command
Run Code Online (Sandbox Code Playgroud)

相反,&&检查第一个命令的退出状态,只有在第一个命令成功时才运行第二个命令。在 shell 脚本中(以及交互使用 shell 时),退出代码 0 表示“真”或“成功”,而任何其他退出代码表示“假”或“失败” .” (这样,程序可以返回不同的错误代码来表示不同类型的错误。)

所以,这里和以前一样,first-command先运行。但如果它不成功,则second-command根本不会运行:

first-command && second-command
Run Code Online (Sandbox Code Playgroud)

这类似于,但不完全相同,使用if

if first-command; then
    second-command
fi
Run Code Online (Sandbox Code Playgroud)

它们的不同之处在于first-command失败时会发生什么。使用&&,整个复合命令的退出状态是返回的任何失败(即非零)退出代码first-command。相反,使用if,当first-command失败时,整个复合命令的退出状态为零(即成功)。


作为一种情况的示例,您实际上可以合理地同时考虑;&&,假设您想运行sudo apt update,它会检索有关从每个配置的软件源中可用的软件包以及版本的最新信息,然后是sudo apt upgrade, 以将您安装的软件包升级到最新的可用版本。这是广泛建议的,也是我通常运行的:

sudo apt update && sudo apt upgrade
Run Code Online (Sandbox Code Playgroud)

由于它使用&&,它运行sudo apt update,但只运行sudo apt upgrade,如果sudo apt update报告说,它成功了。在这些特定命令的情况下,您通常希望这样做的原因是您通常希望检查第一个命令产生的任何错误,以便决定如何继续。

但是您可能会遇到问题,但仍想升级您可以升级的软件包。或者您可能不会想到会出现问题,而只是更愿意继续前进。在这种情况下,您可以将它们分开;(或将它们放在单独的行中,在脚本中):

sudo apt update; sudo apt upgrade
Run Code Online (Sandbox Code Playgroud)

运行sudo apt update,然后sudo apt upgrade不管它是否报告成功都会运行。

这是您实际上可能在两者之间进行选择的情况的示例,因为在这种情况下,第一个命令对第二个命令很重要,但即使第一个命令失败,第二个命令仍然有用。但是,在您想要先运行一个命令然后运行另一个命令的许多情况下,您要么:

  • 第二个命令不依赖于第一个命令,如果第一个命令失败,您仍然希望运行第二个命令,并且它的成功能力预计不会受到影响。然后您通常会;在脚本的不同行中使用或放置它们。
  • 第二个命令完全依赖于第一个命令,因此如果第一个命令失败,尝试第二个命令将毫无意义——或者是有害的。然后你会想用&&它们来分开。

顺便说一下,还有一个||操作员。这仅在第一个命令失败时才运行第二个命令,而不是仅在它成功时(如&&):

first-command || second-command
Run Code Online (Sandbox Code Playgroud)

||不应与|在命令之间建立管道的混淆。