Shell:管道符与重定向
前言
到目前位置自己还没专门花时间研究过Linux
上那些日日都在用的工具(如Shell
和Vim
)他们本来的用法和含义,本来觉得没必要,不过在看了missing-semester
之后顿时感觉效率提高了不少。因此做一个笔记,把一些很实用但是自己并不会去关注的简单用法给记录一下。
参考文章
- Linux shell管道与重定向实例分析
- Shell预览
- How does “<<” operator work in linux shell?
- Precedence of stdin and stdout redirection in Bash
- Redirection and pipe behavior in bash vs. zsh
Shell
prompt
在使用最基础的bash
作为命令行的时候,常常能发现用户后面有的时候是$
二有的时候是#
1 |
|
这里$
代表了当前用户为普通用户,而#
的含义则代表当前是在root
用户下
重定向
输出重定向
在shell
程序中,程序的执行主要分为 输入流 和 输出流 两种不同的流,程序会从输入流中读取信息,然后在通过处理之后打印到输出流当中。
以cat
为例,其作用为将一个文件的内容打印到输出流当中,通过使用 > file
和 < file
来对流进行重定向,可以覆写或者创建对应内容的文件
1 |
|
拓展补充 1:所有的Linux进程都包含3个文件描述符,分别是 标准输入,标准输出 和 错误输出。
标准输入(stdin):对应的文件标识符为0,使用<
或<<
来操作
标准输出(stdout):对应的文件标识符为1,使用>
或>>
来操作
错误输出(stderr): 对应的文件标识符为2,使用2>
或2>>
来操作
默认情况下,标准输出和错误输出都默认为使用者的屏幕,通过使用输出重定向可以做到控制日志的效果补充拓展 2:
>/dev/null 2>&1
和2>&1 >/dev/null
的区别
- 对于
>/dev/null 2>&1
是指先将标准输出指向黑洞设备,然后再将错误输出指向标准输出的指向内容(此时是黑洞),因此标准输出和错误输出都将不输出- 对于
2>&1 >/dev/null
是先将错误输出指向标准输出(此时为屏幕),然后将标准输出指向黑洞,因此此时错误输出将打印到屏幕,而标准输出将不输出
1 |
|
以一个简单的test.cpp程序为例
1 |
|
通过编译并重定向运行
1 |
|
如果希望将对应的文件描述符关闭的话有两种方法
1 |
|
- 对于
>
操作符,首先会判断右侧的文件是否存在,如果存在就删除再创建,如果不存在则直接创建,并且右侧的文件一定会置空。- 一条命令执行前会检查0,1,2三个I/O设备是否正常,如果异常则不会进行命令执行
输入重定向
如果想要将内容输出重定向到某个文件,以cat
举例有两种不同的办法
1 |
|
摘自:How does “<<” operator work in linux shell?
<<
操作符主要有以下三个操作逻辑
- 首先执行该操作符左侧的程序,在上面的例子中就是
cat
- 抓取用户包括换行等所有的输入内容,直到输入的内容为用户指定的EOF结尾内容(在上面的例子中则恰好也是EOF)则停止
- 将所有除了EOF的内容都作为(1)程序的标准输入执行
实例:通过bash
脚本创建一个test.cpp
文件
1 |
|
管道和重定向的使用区别
1、文件类型上
左边的命令应该有标准输出 | 右边的命令应该能接受标准输入;
左边的命令应该有标准输出 > 右边只能是文件;
左边的命令应该需要标准输入 < 右边只能是文件;2、管道触发两个子进程执行 “|” 两边的程序,而重定向是在一个进程内执行。
结合管道的输入重定向
1 |
|
由于标准输入和标准输出在管道运算符中的重定向是发生在"内容输出"之前的,因此可以通过重定向来修改管道中传输的数据
Because pipeline assignment of standard input or standard output or both takes place before redirection, it can be modified by redirection.
举个例子来说,本来管道传输默认只传输标准输出的内容,并不会传输错误输出
1 |
|
通过上面的指令,首先command1
的 错误输出 会在执行前被重定向至标准输入,然后command1
执行,将 标准输出 和 错误输出 一并通过管道进行传输,作为command2
的标准输入
结合管道的输出重定向
1 |
|
>
输出重定向,往往在命令最右边(也可以用到命令中间),接收左边命令的输出结果,重定向到指定文件。
1 |
|
zsh下的重定向与管道传输
在自己实验的时候发现zsh
下即使重定向了标准输出和错误输出依旧可以通过管道读取内容,这主要是zsh有一个可以将输出重定向给多个文件的特性,对于管道也会进行二次传递
参考 Redirection and pipe behavior in bash vs. zsh
Read the MULTIOS documentation in the zshmisc man page. It’s a feature of zsh which causes it to redirect the output to multiple files at the same time, and it can also be a pipe.
具体举例
1 |
|
上面这个命令在bash
当中只有文件a
会有内容,而b
中并没有获取到标准输出。但是在zsh
下执行上面的命令,则a
和b
中都会拥有相同的输出内容。