0%

重导和管道

Shell 重定向与管道:数据流转的核心工具

在 Shell 中,重定向和管道是处理命令输入输出的强大工具,能够灵活控制数据的来源和去向,是实现复杂命令组合和自动化任务的基础。本文将详细解析重定向和管道的用法及实际应用。

重定向:控制命令的输入与输出

重定向通过改变命令默认的输入 / 输出位置(如终端),实现数据写入文件、从文件读取等功能。常用的重定向符号包括 >>>< 等。

输出重定向:>>>

(1)覆盖输出 >
  • 作用:将命令的输出结果覆盖写入到指定文件(若文件不存在则创建,若存在则清空原有内容)。
  • 语法命令 > 文件名

示例

1
2
3
4
5
# 将当前目录列表写入 dir_list.txt(覆盖原有内容)
ls -l > dir_list.txt

# 将系统时间写入 time.log
date > time.log
(2)追加输出 >>
  • 作用:将命令的输出结果追加写入到指定文件(保留原有内容,新内容添加到末尾)。
  • 语法命令 >> 文件名

示例

1
2
3
4
5
# 追加当前时间到 time.log(不覆盖原有内容)
date >> time.log

# 统计用户并追加到 user_list.txt
cat /etc/passwd | cut -d: -f1 >> user_list.txt

输入重定向:<

  • 作用:将命令的输入来源从默认的键盘改为指定文件。
  • 语法命令 < 文件名

示例

1
2
3
4
5
# 从 file.txt 中读取内容作为 grep 的输入(等价于 grep "keyword" file.txt)
grep "error" < file.txt

# 从 input.txt 中读取数据作为 wc 的输入(统计行数)
wc -l < input.txt

错误输出重定向:2>2>>

命令的输出分为标准输出(stdout,文件描述符 1)标准错误(stderr,文件描述符 2)。默认情况下两者都显示在终端,可通过以下符号分离:

  • 2>:将错误输出覆盖写入文件。
  • 2>>:将错误输出追加写入文件。

示例

1
2
3
4
5
# 将错误信息写入 error.log(如删除不存在的文件)
rm no_such_file 2> error.log

# 追加错误信息到 error.log
ls invalid_dir 2>> error.log

特殊设备文件

(1)/dev/null:黑洞设备
  • 任何写入 /dev/null 的数据都会被丢弃(相当于 “删除输出”)。
  • 常用于屏蔽不需要的输出(尤其是错误信息)。

示例

1
2
3
4
5
6
# 执行命令但不显示任何输出(包括错误)
rm no_such_file > /dev/null 2>&1
# 说明:`2>&1` 表示将错误输出(2)重定向到标准输出(1),最终一起写入 /dev/null

# 只屏蔽错误输出,保留正常输出
ls -l 2> /dev/null
(2)/dev/tty:终端设备
  • 表示当前终端,重定向到 /dev/tty 即输出到屏幕(即使标准输出已被重定向)。

示例

1
2
3
# 将正常输出写入文件,但提示信息显示在终端
echo "开始执行任务..." > /dev/tty
ls -l > file_list.txt

管道:连接命令的数据流

管道(|)用于将前一个命令的标准输出作为后一个命令的标准输入,实现多个命令的串联执行,是 Shell 中最强大的特性之一。

基本语法

1
命令1 | 命令2 | 命令3 ...
  • 命令 1 的输出 → 作为命令 2 的输入;
  • 命令 2 的输出 → 作为命令 3 的输入;
  • 以此类推,最终输出到终端或通过重定向写入文件。

常用示例

(1)过滤内容(grep
1
2
3
4
5
# 查找包含 "error" 的日志行
cat app.log | grep "error"

# 查找进程中包含 "java" 的条目
ps aux | grep "java"
(2)统计与排序(wcsortuniq
1
2
3
4
5
6
7
8
# 统计日志中各IP的出现次数并按从高到低排序
cat access.log | awk '{print $1}' | sort | uniq -c | sort -nr

# 说明:
# awk '{print $1}' → 提取日志中的IP(第1列)
# sort → 排序IP(便于后续去重)
# uniq -c → 统计每个IP出现的次数
# sort -nr → 按次数倒序排列(-n 按数字排序,-r 逆序)
(3)分页查看(lessmore
1
2
3
4
5
# 分页查看大文件内容
cat large_file.txt | less

# 分页查看命令输出(如长目录列表)
ls -lR / | more
(4)文本处理(sedawk
1
2
3
4
5
# 替换文件中的 "old" 为 "new" 并输出结果(不修改原文件)
cat file.txt | sed 's/old/new/g'

# 提取CSV文件中第2列和第5列,并用逗号分隔
cat data.csv | awk -F ',' '{print $2 "," $5}'

管道与重定向结合

管道的最终输出可通过重定向写入文件:

1
2
3
# 将过滤后的结果写入文件
ps aux | grep "nginx" | grep -v "grep" > nginx_processes.txt
# 说明:grep -v "grep" 用于排除包含 "grep" 自身的进程

常见误区与注意事项

  1. 管道只传递标准输出
    标准错误(stderr)不会通过管道传递,若需处理错误输出,需先重定向到标准输出:

    1
    2
    # 将错误输出也通过管道传递
    command 2>&1 | grep "error"
  2. 管道中的命令在子进程中执行
    变量赋值等操作在管道中不会影响父 Shell:

    1
    2
    3
    4
    5
    6
    7
    # 错误示例:管道中的赋值无法在外部生效
    echo "123" | read num
    echo $num # 输出为空

    # 正确写法:使用进程替换或here-string
    read num <<< $(echo "123")
    echo $num # 输出:123
  3. 避免过度嵌套
    过多管道串联会降低可读性,复杂逻辑建议拆分或使用脚本

欢迎关注我的其它发布渠道