Merge pull request #11552 from Jamskr/Coupled-commands-with-control-operators-in-Bash

[Translated] Coupled-commands-with-control-operators-in-Bash
This commit is contained in:
Xingyu.Wang 2018-12-09 19:15:15 +08:00 committed by GitHub
commit eca73a7496
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 125 additions and 129 deletions

View File

@ -1,129 +0,0 @@
Translating by Jamskr
Coupled commands with control operators in Bash
======
Add logic to the command line with control operators in compound commands.
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc-lead-yearbook-best-couple.png?itok=a_99oCdE)
Simple compound commands—such as stringing several commands together in a sequence on the command line—are used often. Such commands are separated by semicolons, which define the end of a command. To create a simple series of shell commands on a single line, simply separate each command using a semicolon, like this:
```
command1 ; command2 ; command3 ; command4 ;
```
You don't need to add a final semicolon because pressing the Enter key implies the end of the final command, but it's fine to add it for consistency.
**& &** and **||** control operators built into Bash. These two control operators provide some flow control and enable us to alter the code-execution sequence. The semicolon and the **newline** character are also considered to be Bash control operators.
All the commands will run without a problem—as long as no error occurs. But what happens if an error happens? We can anticipate and allow for errors using theandcontrol operators built into Bash. These two control operators provide some flow control and enable us to alter the code-execution sequence. The semicolon and thecharacter are also considered to be Bash control operators.
The **& &** operator simply says "if command1 is successful, then run command2." If command1 fails for any reason, command2 won't run. That syntax looks like:
```
command1 && command2
```
This works because every command returns a code to the shell that indicates whether it completed successfully or failed during execution. By convention, a return code (RC) of 0 (zero) indicates success and any positive number indicates some type of failure. Some sysadmin tools just return a 1 to indicate any failure, but many use other positive numerical codes to indicate the type of failure.
The Bash shell's **$?** variable can be checked very easily by a script, by the next command in a list of commands, or even directly by a sysadmin. Let's look at RCs. We can run a simple command and immediately check the RC, which will always pertain to the last command that ran.
```
[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 ~]$
```
This RC is 0, which means the command completed successfully. Now try the same command on a directory where we don't have permissions.
```
[student@studentvm1 ~]$ ll /root ; echo "RC = $?"
ls: cannot open directory '/root': Permission denied
RC = 2
[student@studentvm1 ~]$
```
This RC's meaning can be found in the [**ls** command's man page][1].
Let's try the **& &** control operator as it might be used in a command-line program. We'll start with something simple: Create a new directory and, if that is successful, create a new file in it.
We need a directory where we can create other directories. First, create a temporary directory in your home directory where you can do some testing.
```
[student@studentvm1 ~]$ cd ; mkdir testdir
```
Create a new directory in **~/testdir** , which should be empty because you just created it, and then create a new, empty file in that new directory. The following command will do those tasks.
```
[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 ~]$
```
We know everything worked as it should because the **testdir** directory is accessible and writable. Change the permissions on **testdir** so it is no longer accessible to the user **student** as follows:
```
[student@studentvm1 ~]$ chmod 076 testdir ; ll | grep testdir
d---rwxrw-. 3 student student  4096 Nov 12 14:13 testdir
[student@studentvm1 ~]$
```
Using the **grep** command after the long list ( **ll** ) shows the listing for **testdir**. You can see that the user **student** no longer has access to the **testdir** directory. Now let's run almost the same command as before but change it to create a different directory name inside **testdir**.
```
[student@studentvm1 ~]$ mkdir ~/testdir/testdir3 && touch ~/testdir/testdir3/testfile1
mkdir: cannot create directory /home/student/testdir/testdir3: Permission denied
[student@studentvm1 ~]$
```
Although we received an error message, using the **& &** control operator prevents the **touch** command from running because there was an error in creating **testdir3**. This type of command-line logical flow control can prevent errors from compounding and making a real mess of things. But let's make it a little more complicated.
The **||** control operator allows us to add another command that executes when the initial program statement returns a code larger than zero.
```
[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 ~]$
```
Our compound command syntax using flow control takes this general form when we use the **& &** and **||** control operators:
```
preceding commands ; command1 && command2 || command3 ; following commands
```
The compound command using the control operators may be preceded and followed by other commands that can be related to the ones in the flow-control section but which are unaffected by the flow control. All of those commands will execute without regard to anything that takes place inside the flow-control compound command.
These flow-control operators can make working at the command line more efficient by handling decisions and letting us know when a problem has occurred. I use them directly on the command line as well as in scripts.
You can clean up as the root user to delete the directory and its contents.
```
[root@studentvm1 ~]# rm -rf /home/student/testdir
```
How do you use Bash control operators? Let us know in the comment section.
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/11/control-operators-bash-shell
作者:[David Both][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/dboth
[b]: https://github.com/lujun9972
[1]: http://man7.org/linux/man-pages/man1/ls.1.html

View File

@ -0,0 +1,125 @@
Bash 中使用控制运算符连接命令
======
在命令行中,使用控制运算符为复合命令添加逻辑。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc-lead-yearbook-best-couple.png?itok=a_99oCdE)
一些简单的复合指令——比如说在一个命令行中连接几个命令——是经常使用的。这些命令使用分号分隔,表示一个命令结束。为了在一个命令行中创建一系列简单的 shell 命令,只需要使用分号把每一条命令分隔开,就像下面这样:
```
command1 ; command2 ; command3 ; command4 ;
```
最后一个分号你可以不用添加,因为当你按下回车键时就表示一个命令的结束,但是为了和其它的保持一致,还是建议加上比较好。
所有的命令执行都没有什么问题——只要没有什么意外发生。但是当出问题时到底发生了什么呢?我们可以预测,并且通过 Bash 中内置的 `&&``||` 运算符跟踪这些错误。这两个控制运算符提供了一些流控制,可以让我们改变代码执行队列的顺序。分号和 **换行符** 也被认为是 Bash 的控制运算符。
`&&` 运算符意义简单来说就是“如果 `command1` 执行成功,就接着执行 `command2`。”如果 `command1` 因为任何原因执行失败,那么 `command2` 将不执行。这个语法看下来像这样:
```
command1 && command2
```
这样写是允许的,因为每一个命令都会返回一个值给 shell 来表示这个命令在执行的过程中是否执行成功或者失败。通常,返回值是 0 表示成功,而一个正数值表示不同种类的错误。有一些系统管理工具仅仅返回一个 1 来表示所有的错误,但是也有很多工具使用其它的正数的返回值来表示各种类型错误。
我们可以很容易的使用脚本, 命令列表中的下一个命令,或者可以直接使用系统管理工具来检查 shell 变量 `$?` 。我们一起来看这些返回值。运行一个简单的命令然后立即检查它的返回值,这个返回值始终是属于最后一个运行的命令。
```
[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 ~]$
```
这个返回值是 0表示这个命令执行成功了。现在尝试使用同样的命令在一些我们没有权限的目录上。
```
[student@studentvm1 ~]$ ll /root ; echo "RC = $?"
ls: cannot open directory '/root': Permission denied
RC = 2
[student@studentvm1 ~]$
```
这个返回值的含义可以在 [`ls` 命令的 man 页面][1] 中找到。
现在我们来试试 `&&` 这个控制运算符,因为它也可能会被用在一个命令行程序中。我们将从一个简单的示例开始:创建一个新目录,如果创建成功就在这个目录中创建一个文件。
我们需要一个目录可以创建其它的目录。首先,在你的家目录中创建一个临时的目录用来做测试。
```
[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` 目录的时候发生了错误。通过这种复合的流控制可以阻止一些错误的发生使事情变乱。但是这样看起来变得稍微复杂了一些。
`||` 控制运算符允许添加另一个命令,这个命令在初始程序语句返回值大于 0 时执行。
```
[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 控制运算符的呢?在评论区中告诉我们。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/11/control-operators-bash-shell
作者:[David Both][a]
选题:[lujun9972][b]
译者:[Jamskr](https://github.com/Jamskr)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/dboth
[b]: https://github.com/lujun9972
[1]: http://man7.org/linux/man-pages/man1/ls.1.html