Bash 中使用控制操作符的耦合命令

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

互联网档案馆。由 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 许可协议本作品根据 Creative Commons 署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.