Shell 的命令
Bash命令的类别
Shell 的命令
命令的类别
Bash可以使用的命令分成四类。
- 可执行程序
- Shell 提供的命令
- Shell 函数
- 前三类命令的别名
type, whatis
type
命令可以显示命令类型。
下面是几个例子。
whatis
命令显示指定命令的描述。
apropos
apropos
命令返回符合搜索条件的命令列表。
alias, unalias
alias
命令用来为命令起别名。
上面命令指定foo
为三个命令的别名。以后,执行foo
就相当于一起执行这三条命令。
注意,默认情况下,别名只在当前Session有效。当前Session结束时,这些别名就会消失。
alias
命令不加参数时,显示所有有效的别名。
unalias
命令用来取消别名。
which
which
命令显示可执行程序的路径。
which
命令用于Shell内置命令时(比如cd
),将没有任何输出。
help,man
help
命令用于查看Shell内置命令的帮助信息,man
命令用于查看可执行命令的帮助信息。
man
里面的文档一共有8类,如果同一个命令,匹配多个文档,man
命令总是返回第一个匹配。如果想看指定类型的文档,命令可以采用下面的形式。
script
script
命令会将输入的命令和它的输出,都保存进一个文件。
如果没有指定文件名,则所有结果会保存进当前目录下typescript
文件。结束录制的时候,可以按下Ctrl + d
。
export
export
命令用于将当前进程的变量,输出到所有子进程。
命令的连续执行
多个命令可以写在一起。
Bash 提供三种方式,定义它们如何执行。
上面三种执行方法的退出码,都是最后一条执行的命令的退出码。
bash 允许把命令组合在一起。可以通过两种方式完成;要么用一个 group 命令,要么用一个子 shell。 这里是每种方式的语法示例:
组命令:
子 shell
这两种形式的不同之处在于,组命令用花括号把它的命令包裹起来,而子 shell 用括号。值得注意的是,鉴于 bash 实现组命令的方式, 花括号与命令之间必须有一个空格,并且最后一个命令必须用一个分号或者一个换行符终止。
那么组命令和子 shell 命令对什么有好处呢? 它们都是用来管理重定向的。
使用一个子 shell 是相似的。
组命令和子 shell 真正闪光的地方是与管道线相结合。 当构建一个管道线命令的时候,通常把几个命令的输出结果合并成一个流是很有用的。 组命令和子 shell 使这种操作变得很简单。
这里我们已经把我们的三个命令的输出结果合并在一起,并把它们用管道输送给命令 lpr 的输入,以便产生一个打印报告。
虽然组命令和子 shell 看起来相似,并且它们都能用来在重定向中合并流,但是两者之间有一个很重要的不同。 然而,一个组命令在当前 shell 中执行它的所有命令,而一个子 shell(顾名思义)在当前 shell 的一个 子副本中执行它的命令。这意味着运行环境被复制给了一个新的 shell 实例。当这个子 shell 退出时,环境副本会消失, 所以在子 shell 环境(包括变量赋值)中的任何更改也会消失。因此,在大多数情况下,除非脚本要求一个子 shell, 组命令比子 shell 更受欢迎。组命令运行很快并且占用的内存也少。
当我们发现管道线中的一个 read 命令 不按我们所期望的那样工作的时候。为了重现问题,我们构建一个像这样的管道线:
该 REPLY 变量的内容总是为空,是因为这个 read 命令在一个子 shell 中执行,所以它的 REPLY 副本会被毁掉, 当该子 shell 终止的时候。因为管道线中的命令总是在子 shell 中执行,任何给变量赋值的命令都会遭遇这样的问题。 幸运地是,shell 提供了一种奇异的展开方式,叫做进程替换,它可以用来解决这种麻烦。进程替换有两种表达方式:
一种适用于产生标准输出的进程:
另一种适用于接受标准输入的进程:
这里的 list 是一串命令列表:
为了解决我们的 read 命令问题,我们可以雇佣进程替换,像这样。
进程替换允许我们把一个子 shell 的输出结果当作一个用于重定向的普通文件。事实上,因为它是一种展开形式,我们可以检验它的真实值:
通过使用 echo 命令,查看展开结果,我们看到子 shell 的输出结果,由一个名为 /dev/fd/63 的文件提供。