这里介绍Shell常用的命令连接、分组方式
命令连接
分号 ;
依次执行所有命令,无论前面的命令执行结果是成功还是失败
1 | # 依次执行下述命令 |
逻辑与 &&
只有在前一个命令执行成功后,才会执行下一个命令。与Java中短路求值机制很类似
1 | # 只有在前一个命令执行成功后,才会执行下一个命令 |
逻辑或 ||
前一个命令执行成功,则后面的命令不会执行;只有在前一个命令执行失败后,才会执行下一个命令。与Java中短路求值机制很类似
1 | # 只有在前一个命令执行失败后,才会执行下一个命令 |
命令分组
语法
使用()分组时其会创建子shell,使得括号中的每个命令都在该子shell中执行。由于命令是在子shell中执行的,因此在子shell完成后变量分配不会影响父shell。语法规则如下,(左括号的后面、)右括号的前面必须要有一个空格。括号中的最后一个命令后面的分号不是必须的
1 | ( date ; ls -ld ; cat main.java ; ) |
使用{}分组时,括号的每个命令都会在当前shell中执行,不会创建子shell。语法规则如下,{左括号的后面、}右括号的前面必须要有一个空格。同时,括号中的最后一个命令后的分号必须要有
1 | # 命令列表中的最后一个命令后的分号必须要有 |
区别
这里我们使用的Shell为zsh,故可通过ZSH_SUBSHELL变量的值判断当前shell是否为子shell。该变量值为0时,表示该shell不是子shell;该变量值如果比0大,则表明是子shell。该值可以表示当前子shell的嵌套级别。例如,父shell的值是0,子shell的值为1,子shell的子shell值是2,以此类推。同时,由于cd命令切换目录时会设置环境变量PWD,而pwd命令则通过读取环境变量PWD获取当前路径信息。至此,我们就可以验证两种分组方式的影响、区别
1 | # 使用()分组 |
通过ZSH_SUBSHELL变量的值可以证明()分组中的命令是在子shell当中执行的;同时,在子shell中的更改操作(例如,对变量值进行修改),一旦子shell结束后,所有更改都会消失。故通过()分组执行完毕后,不会修改当前路径;而通过{}分组执行完毕后,当前路径则会被更新
场景
常见的使用命令分组的场景有:
1. 多条命令的输出需要重定向到同一个文件
1 | # 分别重定向 |
2. 对多条命令整体进行有条件连接
1 | # 如果b.txt文件不存在,则创建、写入该文件 |
参考文献
- Linux命令行与shell脚本编程大全·第4版 Richard Blum、Christine Bresnahan著