以下链接命令的方法有什么区别?
cmd1; cmd2
cmd1 && cmd2
答案1
假设有command1 && command2
.
在这种情况下,当且仅当返回零退出状态command2
时才会执行。command1
;
只是一个命令分隔符。因此command2
将执行command1
返回的任何内容。
$> [[ "a" = "b" ]] && echo ok
$> [[ "a" = "b" ]]; echo ok
ok
答案2
cmd1; cmd2
执行cmd1
,然后cmd2
,无论如何。它完全相当于将cmd1
和cmd2
放在不同的行上。该复合命令的返回状态是 的返回状态cmd2
。
cmd1 && cmd2
执行cmd1
.然后,如果 的退出状态cmd1
为零,cmd2
则执行。该复合命令的返回状态是cmd1
如果它非零(因此cmd2
没有运行),否则返回状态cmd2
(如果它运行)。
if cmd1; then cmd2; fi
大多数情况下相当于cmd1 && cmd2
.主要区别在于,如果返回非零状态,if
则返回 0 的版本。cmd1
命令返回 0 表示成功,返回非零错误代码(1 到 255 之间,通常在 1 到 125 之间,因为较高的值有其他含义)表示失败。因此cmd1; cmd2
意味着“无论如何都按顺序执行这些命令”,而cmd1 && cmd2
意味着“执行这些命令,但如果第一个命令失败则立即停止”。
您可以通过运行命令 shell 进入“错误退出”模式set -e
。在此模式下,只要任何命令返回非零状态,shell 就会退出,但条件结构( &&
or的左侧、 and||
的条件部分)除外。因此,under , (或换行符)实际上相当于²。if
while
set -e
;
&&
1就控制流而言,就是这样。换行符和分号以完全相同的方式执行,但它们的解析方式并不完全相同,因此例如alias ls=true; ls
执行ls
而不是true
因为解析器在ls
执行别名定义之前执行别名解析。
1这并不是说&&
如果;
您添加了set -e
.例如,;
的优先级低于&&
,因此cmd1 && cmd2 || cmd3
相当于set -e; { cmd1; cmd2; } || cmd3
。此外,set -e
与子 shell 的交互很糟糕——细节会使这个答案偏离太多。
答案3
第一行将执行一个又一个命令,无论第一个命令是否成功。第二行是 shell 逻辑的示例:如果第一个命令成功,它只会执行第二个命令。这是因为&&
符合逻辑and
。因此,如果第一个命令失败,则整条线的逻辑状态已知为假,并且无需评估第二个命令。
答案4
更实际的是,两者之间有区别
cd /backup/old; rm -rf -- *
和
cd /backup/old && rm -rf -- *
。除此之外,这是一种愚蠢的方法,第一个方法将删除您的整个文件系统(或 $HOME,取决于它的调用方式),因为rm
无论cd
成功与否它都会运行。