Skip to main content

Linux 重定向与管道

Linux 管道工作原理与使用

管道(|)是 Linux 命令行里超级好用的工具,它能让命令像流水线一样协作,把一个命令的输出直接传给另一个命令当输入。

基于 stdin、stdout 和 stderr 的知识,管道主要处理 stdout 和 stdin,让你轻松组合命令来完成复杂任务。

1. 什么是管道?

管道用 | 符号表示,它的作用是把左边命令的 stdout 直接送给右边命令的 stdin。简单说,就是让命令“串联”起来,像接水管一样,数据从一个命令流到下一个。

比如:

ls | grep "txt"

这里:

  • ls 的 stdout(当前目录的文件列表)通过管道传给 grep
  • grep "txt" 从 stdin 读取数据,过滤出包含 “txt” 的行。

结果是只显示文件名中包含 “txt” 的文件。

2. 管道的工作原理

管道的核心是把 stdout 和 stdin 连接起来。Linux 会:

  1. 运行左边的命令,把它的 stdout 临时存到一个内存缓冲区。
  2. 把这个缓冲区的内容作为右边命令的 stdin。
  3. 右边命令处理输入,输出结果(通常是 stdout,显示在终端)。

重要提醒:

  • 管道只传 stdout,不传 stderr。stderr 默认还是显示在终端。
  • 管道是单向的,数据从左到右流动。

试试这个:

ls /etc /notexist | grep "conf"
  • ls /etc /notexist 会输出 /etc 的文件列表(stdout),同时在终端显示错误(stderr:ls: cannot access '/notexist': No such file or directory)。
  • grep "conf" 只从 stdin(即 /etc 的文件列表)过滤出包含 “conf” 的行。

3. 基本用法:单个管道

单个管道是最简单的用法,把两个命令连起来:

echo "apple banana cherry" | tr 'a' 'A'
  • echo 输出 “apple banana cherry” 到 stdout。
  • tr 'a' 'A' 从 stdin 读取,把小写 a 替换成大写 A

结果是:

Apple bAnAnA cherry

另一个例子:

cat file.txt | sort

如果 file.txt 包含几行文本,cat 把内容送到 stdout,sort 从 stdin 读取并按字母顺序排序后输出。

4. 多管道:串联多个命令

管道可以无限串联,组成复杂的处理链。比如:

ls /etc | grep "conf" | sort | head -n 2

这行命令:

  1. ls /etc 列出 /etc 目录的内容。
  2. grep "conf" 过滤出包含 “conf” 的行。
  3. sort 按字母顺序排序。
  4. head -n 2 只取前两行。

每个命令的 stdout 都成为下一个命令的 stdin,层层处理。

5. 管道与重定向结合

管道和重定向可以一起用,灵活处理输入输出。比如:

ls /etc | grep "conf" > output.txt
  • ls /etc | grep "conf":管道过滤出包含 “conf” 的文件。
  • > output.txt:把 grep 的 stdout 写入 output.txt

再来个复杂点的:

cat input.txt | grep "error" > output.txt 2> error.log
  • cat input.txt 的 stdout 送到 grep
  • grep "error" 过滤出包含 “error” 的行,输出到 stdout。
  • > output.txtgrep 的 stdout 存到 output.txt
  • 2> error.loggrep 的 stderr(如果有)存到 error.log

6. 处理 stderr 在管道中

管道默认只传 stdout,stderr 不会进入管道。如果想让 stderr 也参与管道,需要先把 stderr 重定向到 stdout。用 2>&1

ls /etc /notexist 2>&1 | grep "conf"
  • 2>&1 把 stderr 合并到 stdout。
  • 合并后的输出(stdout + stderr)通过管道送到 grep
  • grep "conf" 过滤包含 “conf” 的行(可能包括错误信息)。

试试看,输出可能包含错误信息(如果错误信息里带 “conf”)。

7. 使用 tee:在管道中保存中间结果

有时候你想在管道处理的同时,把中间结果存到文件,这可以用 tee 命令。tee 从 stdin 读取数据,同时写到文件和 stdout。

比如:

ls /etc | grep "conf" | tee conf_files.txt | sort
  • ls /etc | grep "conf":过滤出包含 “conf” 的文件。
  • tee conf_files.txt:把 grep 的输出存到 conf_files.txt,同时继续传给下一个命令。
  • sort:对结果排序。

运行后,conf_files.txt 存了 grep 的输出,终端显示排序后的结果。

8. 常见管道命令组合

以下是一些超实用的管道组合:

  • 统计行数
cat file.txt | wc -l

wc -l 从 stdin 读取,统计行数。

  • 查找并排序唯一项
cat file.txt | sort | uniq

sort 排序,uniq 删除重复行。

  • 过滤并计数
dmesg | grep "error" | wc -l

统计内核日志(dmesg)中包含 “error” 的行数。