Bash 中使用控制运算符的耦合命令

使用复合命令中的控制运算符向命令行添加逻辑。
291 位读者喜欢这篇文章。
Best couple of cats

Internet Archive。由 Opensource.com 修改。CC BY-SA 4.0

简单的复合命令(例如,在命令行中将多个命令按顺序连接在一起)经常使用。这些命令用分号分隔,分号定义了一个命令的结束。要在单行上创建一系列简单的 shell 命令,只需使用分号分隔每个命令,如下所示

command1 ; command2 ; command3 ; command4 ; 

您不需要添加最后一个分号,因为按 Enter 键表示最后一个命令的结束,但为了保持一致性,添加它也可以。

所有命令都将顺利运行——只要不发生错误。但是如果发生错误会怎么样?我们可以使用 Bash 内置的 &&|| 控制运算符来预测和处理错误。这两个控制运算符提供了一些流程控制,使我们能够更改代码执行顺序。分号和换行符也被认为是 Bash 控制运算符。

&& 运算符的意思是“如果 command1 成功,则运行 command2”。如果 command1 因任何原因失败,则 command2 将不会运行。该语法如下所示

command1 && command2

这之所以有效,是因为每个命令都会向 shell 返回一个代码,指示它是否成功完成或在执行期间失败。按照惯例,返回代码 (RC) 为 0(零)表示成功,任何正数表示某种类型的失败。一些系统管理员工具只返回 1 来表示任何失败,但许多工具使用其他正数值代码来指示失败的类型。

Bash shell 的 $? 变量可以很容易地通过脚本、命令列表中的下一个命令,甚至直接由系统管理员检查。让我们看看 RC。我们可以运行一个简单的命令并立即检查 RC,它将始终与上次运行的命令有关。

[student@studentvm1 ~]$ ll ; echo "RC = $?"
total 284
-rw-rw-r--  1 student student   130 Sep 15 16:21 ascii-program.sh
drwxrwxr-x  2 student student  4096 Nov 10 11:09 bin
<snip>
drwxr-xr-x. 2 student student  4096 Aug 18 10:21 Videos
RC = 0
[student@studentvm1 ~]$

此 RC 为 0,这意味着命令已成功完成。现在在没有权限的目录上尝试相同的命令。

[student@studentvm1 ~]$ ll /root ; echo "RC = $?"
ls: cannot open directory '/root': Permission denied
RC = 2
[student@studentvm1 ~]$

此 RC 的含义可以在 ls 命令的手册页中找到。

让我们尝试 && 控制运算符,因为它可能在命令行程序中使用。我们将从一些简单的内容开始:创建一个新目录,如果成功,则在其中创建一个新文件。

我们需要一个可以创建其他目录的目录。首先,在您的主目录中创建一个临时目录,您可以在其中进行一些测试。

[student@studentvm1 ~]$ cd ; mkdir testdir

~/testdir 中创建一个新目录,它应该是空的,因为您刚刚创建了它,然后在该新目录中创建一个新的空文件。以下命令将执行这些任务。

[student@studentvm1 ~]$ mkdir ~/testdir/testdir2 && touch ~/testdir/testdir2/testfile1 
[student@studentvm1 ~]$ ll ~/testdir/testdir2/
total 0
-rw-rw-r-- 1 student student 0 Nov 12 14:13 testfile1
[student@studentvm1 ~]$

我们知道一切都按预期工作,因为 testdir 目录是可访问且可写的。更改 testdir 的权限,使其不再可供用户 student 访问,如下所示

[student@studentvm1 ~]$ chmod 076 testdir ; ll | grep testdir
d---rwxrw-. 3 student student  4096 Nov 12 14:13 testdir
[student@studentvm1 ~]$

在长列表 (ll) 之后使用 grep 命令显示 testdir 的列表。您可以看到用户 student 不再有权访问 testdir 目录。现在让我们运行几乎相同的命令,但将其更改为在 testdir 中创建不同的目录名称。

[student@studentvm1 ~]$ mkdir ~/testdir/testdir3 && touch ~/testdir/testdir3/testfile1 
mkdir: cannot create directory ‘/home/student/testdir/testdir3’: Permission denied
[student@studentvm1 ~]$

虽然我们收到了错误消息,但使用 && 控制运算符阻止了 touch 命令的运行,因为在创建 testdir3 时出现错误。这种类型的命令行逻辑流程控制可以防止错误复合并造成真正的混乱。但让我们让它更复杂一点。

|| 控制运算符允许我们添加另一个命令,该命令在初始程序语句返回大于零的代码时执行。

[student@studentvm1 ~]$ mkdir ~/testdir/testdir3 && touch ~/testdir/testdir3/testfile1 || echo "An error occurred while creating the directory."
mkdir: cannot create directory ‘/home/student/testdir/testdir3’: Permission denied
An error occurred while creating the directory.
[student@studentvm1 ~]$ 

当我们使用 &&|| 控制运算符时,我们的使用流程控制的复合命令语法采用这种通用形式

preceding commands ; command1 && command2 || command3 ; following commands

使用控制运算符的复合命令可以在流程控制部分中的命令之前和之后添加其他命令,这些命令可能与流程控制部分中的命令相关,但不受流程控制的影响。所有这些命令都将执行,而无需考虑流程控制复合命令内部发生的任何事情。

这些流程控制运算符可以通过处理决策并在问题发生时通知我们,从而提高在命令行工作的效率。我直接在命令行以及脚本中使用它们。

您可以作为 root 用户清理以删除目录及其内容。

[root@studentvm1 ~]# rm -rf /home/student/testdir

您如何使用 Bash 控制运算符?请在评论区告诉我们。

David Both
David Both 是一位开源软件和 GNU/Linux 倡导者、培训师、作家和演说家。自 1996 年以来,他一直从事 Linux 和开源软件方面的工作,自 1969 年以来一直从事计算机方面的工作。他是“系统管理员 Linux 哲学”的坚定拥护者和传播者。

5 条评论

有趣,David。我一直对 && 运算符感到疑惑,你证实了我的猜测。
在你使用 || 生成错误消息的示例中,难道你不会从失败的 mkdir 命令中收到此消息吗?涉及到如此多的输入,对我来说输入单个命令似乎更容易。

感谢您的评论,Greg。是的 - 这种方式肯定需要更多输入,并且大多数命令都会生成自己的错误消息。此示例仅用于说明目的,并提供了一种简单的方法来描述 && 和 || 运算符的功能。

回复 ,作者:Greg P

大多数像这样的文章都谈论 bash,但上述内容也适用于 csh、ksh 以及我所知道的任何其他 shell。

另一个提示
我的配置文件中有以下行
export PS1="(\$?)[\u@\H \W]\\$ "
它将永久显示 RC

例如:

mountpoint -q /srv && rsync /var/some/path /srv/some/other/path

仅当目录 /srv 用作挂载点时才运行 rsync。

Creative Commons License本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.