shell重定向详解
探秘 Shell 重定向:让你的命令行“指哪打哪”
你以为命令行只是敲敲命令?错!学会了重定向,你就能让数据像听话的小狗一样,想去哪就去哪。
前言:命令行的“水管工”必修课
如果你刚接触 Linux 或 macOS 的终端,可能会觉得命令行像个“黑盒子”——输入一条命令,屏幕就“吐”出一堆文字。但你有没有想过:
- 怎么把命令的输出保存到文件里,而不是只显示在屏幕上?
- 怎么把文件内容喂给命令当输入?
- 怎么把报错信息单独拎出来,不让它和正常输出混在一起?
答案就是 —— Shell 重定向。说白了,它就是命令行的“水管工”,负责把数据的源头和去处重新接一接。
准备好了吗?让我们撸起袖子,开始这场“水管改造”之旅。
一、先搞懂三个“水管口”
每个 Linux 命令启动时,系统都会给它配好三根默认的“水管”:
| 水管名字 | 编号(文件描述符) | 默认去向 | 通俗比喻 |
|---|---|---|---|
| 标准输入 | 0 | 键盘 | 水龙头(进水) |
| 标准输出 | 1 | 屏幕 | 出水管(正常水) |
| 标准错误 | 2 | 屏幕 | 出水管(污水) |
💡 小知识:为什么错误和输出默认都往屏幕跑?因为设计者觉得“正常消息”和“错误消息”你都应该立刻看到。但你可以把它们分开,后面会讲。
二、基础重定向:三招玩转 > 和 >>
1. 输出重定向 > —— “覆盖式倒水”
把命令的标准输出倒进文件,屏幕就看不到了。
# 把当前目录列表写入 list.txt(如果文件存在,会覆盖掉原来的内容) |
注意:> 是覆盖模式,相当于“清空文件再写”。小心别把重要文件覆盖了!
2. 追加重定向 >> —— “接水式追加”
想保留文件原有内容,只在末尾追加?用 >>。
# 先写第一行 |
3. 错误重定向 2> —— “单独收集污水”
默认错误和输出都显示在屏幕上,但你可以把错误单独存下来。
# 找一个不存在的文件,会产生错误 |
🧙♂️ 魔法编号:
2>中的2就是文件描述符(标准错误)。1>可以省略1,因为>默认就是标准输出。
4. 同时重定向输出和错误 —— “分流还是合流?”
方法一:分两个文件存
command > output.log 2> error.log |
方法二:都扔进同一个文件(合流)
老式写法(兼容所有 shell):
command > all.log 2>&1
解释:先把标准输出指向
all.log,然后2>&1表示“让标准错误也去标准输出当前去的地方”。现代简写(bash / zsh 支持):
command &> all.log
# 或者
command >& all.log
🍺 喝啤酒的比喻:
2>&1就像你跟朋友说“他的杯子空了,你就把你的酒倒给他”——错误输出跟着输出走。
三、输入重定向 < —— “让命令从文件里吃饭”
默认命令从键盘读取输入,但你可以用 < 让命令从文件读取。
# 普通用法:wc 统计文件单词数 |
也可以和输出重定向连用,形成管道线的替代方案:
# 从 input.txt 读,排序后写到 output.txt |
四、终极合体技:管道 | —— “命令接龙”
重定向的集大成者其实是管道。它不经过中间文件,直接把左边命令的输出“喂”给右边命令作为输入。
# 查看历史命令中 grep 用了多少次 |
🎢 管道的乐趣就像游乐园的滑水道——数据从上一个滑梯滑进下一个,一滴水都不浪费。
管道 vs 重定向:一张表看懂
| 特点 | 管道 | | 重定向 > / < |
| :— | :— | :— |
| 连接对象 | 命令 ↔ 命令 | 命令 ↔ 文件 |
| 是否存盘 | 不存盘,内存传递 | 最终写入文件 |
| 典型场景 | 数据流式处理 | 保存结果 / 读取配置 |
五、进阶技巧:让你的命令行“开挂”
1. tee 命令 —— “分流兼偷看”
有时候你想既把输出存到文件,又能在屏幕上看到,怎么办?tee 就是你的“复制水阀”。
# 运行命令,屏幕实时显示,同时写入 result.log |
2. Here Document —— “直接在脚本里写多行输入”
在 shell 脚本中,你想给命令提供多行输入,但又不想单独建个文件。用 << 加一个分界符。
cat << EOF > hello.txt |
如果不想展开变量(比如 $HOME 原样输出),把分界符用引号包起来:
cat << 'EOF' > raw.txt |
3. Here String —— “单行输入快捷方式”
<<< 可以把一个字符串当作标准输入送给命令。
# 统计单词数 |
4. 重定向到 /dev/null —— “扔进黑洞”
不想看到任何输出(包括错误)?扔进 /dev/null,这个“系统黑洞”会吞掉一切。
# 安静地执行命令,不产生任何屏幕输出 |
常用于后台脚本或测试环境。
六、实战小剧场:三个真实场景
场景一:编译软件时只保存错误
make 1> build_output.log 2> build_error.log |
正常编译日志进 build_output.log,只有警告和错误进 build_error.log。排查问题超方便。
场景二:自动备份脚本,并记录时间戳
|
用 { ... } 把多行命令的输出一起重定向,干净利落。
场景三:交互式程序自动化(比如 ftp)
ftp -n << EOF |
把所有 ftp 命令通过 Here Document 喂进去,完成自动下载。
七、避坑指南(老司机血泪经验)
| ❌ 错误写法 | 后果 | ✅ 正确写法 |
|---|---|---|
command > file 2>file |
两个流争抢写同一个文件,可能乱码或丢失 | command &> file 或 command > file 2>&1 |
command 2>&1 > file |
2>&1 在前时,标准错误还指向屏幕(因为当时标准输出还在屏幕) |
command > file 2>&1 (顺序调换) |
echo "text" > /proc/somefile |
特殊文件(如 /proc 下)不能随意覆盖 |
确认文件是普通文件再重定向 |
cat file > file |
清空 file 后再读它?文件先被截断,啥也读不到 | 用临时文件或 sponge(`cat file |
🚨 记住:重定向的解析顺序是从左到右,
2>&1必须在> file之后才能让错误也进文件。
八、彩蛋:一个“无用但有趣”的重定向
# 把自己写的代码打印出来,再编译运行,再输出……(别在生产环境玩) |
或者玩一把“读自己的源代码”:
# 一个自指的命令 |
总结:重定向三板斧
- 输出:
>覆盖,>>追加,2>错误单独存。 - 输入:
<从文件读,<<Here Document 多行输入,<<<Here String 单行。 - 合体:
|管道连接命令,tee分流显示,&>合并输出与错误。
掌握了重定向,你的命令行就不再是单向的“广播”,而变成了可以任意编排的“数据乐高”。不管是写脚本、分析日志,还是日常骚操作,都能指哪打哪,得心应手。
📖 延伸阅读:
man bash搜索 “REDIRECTION”,或者看看info coreutils 'Standard I/O'。
💬 喜欢这篇文章?欢迎在评论区分享你遇到过的“重定向翻车现场”!
Happy Hacking! 🐧
