前言
在LINUX系统中,往往一个命令只实现简单的操作,例如ls、cat、head、tail等等。复杂的操作,一般情况下是简单命令的作用。这得益于Linux的重定向与管道功能,能够将一些列简单的指令组合来完成复杂的操作。另外,重定向与管道能够应用的一个基础是LINUX中的处理绝大数都是文本形式,这相当于命令的输入输出参数有了统一的形式。
重定向
在计算机中,一般情况下的默认输入为键盘,输出为显示屏。重定向是一种将标准输入(stdin)和标准输出(stdout)从它们的默认设备转移到文件或其他设备的技术。即重定向则允许用户能够指定特定的输入来源,而非键盘这一个来源。
前置知识
文件描述符
在LINUX中所有执行I/O操作的系统调用都是以文件描述符的形式进行,而文件描述符(fd,file discription)其实就是一个非负整数,用来指代打开的文件。一般情况下,一个进程可能打开的文件不止一个。在整个系统中会存在大量被打开的文件,同时还会对文件进行操作(这会涉及到文件内容偏移),操作系统对文件操作会进行管理和记录。在实际的LINUX系统中操作系统通过数据结构对文件数据进行组织和管理。具体的组织与管理如下:
在上图中,task_struct结构体为进程控制块PCB(Process Control Block)或进程描述符PD用来控制与管理进程。每一个进程都有一个file的指针数组(文件描述符表),这个数组的表项保存着一个指向打开文件的指针。所有,进程就可以通过数组的下标索引找到对应的文件,而这个下标索引就是文件描述符。
标准输入、标准输出、标准错误输出
Linux 系统中,标准输入输出是由系统内核管理的,它们通过文件描述符提供给应用程序。文件描述符是一个整数,用以标识一个已打开的文件。在C语言中,scanf和printf函数用于标准输入和标准输出的输入输出操作。而在Linux中,STDIN_FILENO和STDOUT_FILENO是用于表示标准输入和标准输出的文件描述符。
文件描述符 | 用途 | POSIX名称 | stdio流 |
0 | 标准输入 | STDIN _ FILENO | stdin |
1 | 标准输出 | STDOUT _ FILENO | stdout |
2 | 标准错误 | STDERR _ FILENO | stderr |
实现原理
fd分配原则
- 文件描述符0、1、2被系统固定分配给标准输入、标准输出以及标准错误。其他的文件的分配需要从3开始。
- 使用当前没有被使用的fd中最小的一个下标给打开的文件。
重定向的本质
在操作系统内部更改文件操作符fd的内容指向
重定向命令
命令 | 描述 | 示例 |
---|---|---|
> | 输出重定向:命令的标准输(stdout)重定向到文件中,如果文件已存在,它会被覆盖。如果文件不存在,它会被创建。 | echo "Hello World" > output.txt |
>> | 输出追加:将命令的标准输出追加到文件的末尾。如果文件不存在,它会被创建。 | echo "Hello Again" >> output.txt |
2> | 错误重定向:将标准错误重定向到文件中。如果文件已存在,它会被覆盖。 | ls non_existing_file 2> error.log |
2>> | 错误追加重定向:将标准错误追加到文件中。 | ls non_existing_file 2>> error.log |
&> | 合并输出和错误:将标准输出和标准错误都重定向到同一个文件中。如果文件已存在,它会被覆盖。 | ls non_existing_file &> output_and_error.log |
&>> | 合并输出和错误追加:将标准输出和标准错误都追加到同一个文件中 | ls non_existing_file 2>> error.log |
< | 输入重定向:将文件内容作为命令的标准输入 | grep error < log.txt |