用 > 或 >> 保存输出时需注意:> 只捕获 stdout,stderr 会丢失;要保存全部输出须用 &> 或 > file 2>&1;> 覆盖文件有风险,可用 set -C 防误覆盖;重定向顺序影响结果,应先 stdout 后 stderr;tee 可同时显示与保存,/dev/null 用于丢弃输出。

直接用 > 或 >> 就能保存,但多数人漏掉错误信息、误覆盖文件、或搞错重定向顺序——结果文件里空空如也,还以为命令没执行。
为什么 ls > output.txt 有时文件是空的
因为 ls 报错(比如目录不存在)时,错误信息走的是 stderr(文件描述符 2),而 > 只捕获 stdout(文件描述符 1)。终端上一闪而过的报错,根本没进文件。
- 验证方法:运行
ls /no/such/dir > out.txt 2>/dev/null,out.txt空;再跑ls /no/such/dir 2>err.txt,err.txt就有内容 - 真正要“存全所有输出”,必须显式合并 stderr:用
> output.txt 2>&1或更简洁的&> output.txt -
&>在 bash/zsh 中可用,但在 dash(如 Ubuntu 的 /bin/sh)里不支持,脚本中需谨慎
> 和 >> 的实际区别不只是“覆盖 vs 追加”
> 会清空目标文件再写,哪怕你只打算写一行;>> 是原子追加,适合日志,但得防文件无限膨胀。
-
>风险点:手误输错文件名,比如cat config.json > confg.json,原confg.json被清空且不可恢复 - 临时防护:执行前先运行
set -C(等价于set -o noclobber),之后>遇到已存在文件会报错:bash: output.txt: Cannot overwrite - 想强制覆盖?用
>| output.txt(在set -C生效时) -
>>不检查文件是否存在,不存在就新建,存在就追加——但要注意权限:如果文件只读,追加也会失败
如何同时保存 stdout 和 stderr 到不同文件
调试时经常需要分开看正常输出和错误堆栈,比如跑一个脚本:./deploy.sh > log.txt 2> error.txt。
- 顺序不能颠倒:
2> error.txt > log.txt是错的——shell 按从左到右解析,2>先执行,此时 stdout 还连着终端,>后才把 stdout 重定向到log.txt,结果 stderr 写进了error.txt,stdout 却进了终端 - 追加模式也同理:
>>和2>>(注意中间无空格)对应追加 stdout 和 stderr,但更清晰写法是> log.txt 2>> error.txt - 想把两者都追加到同一文件?用
&>> combined.log(bash 4.0+),或老式写法>> combined.log 2>&1
别硬写文件:什么时候该用 tee 或 /dev/null
重定向不是万能解法。你想看输出又存文件?或者只想知道命令成没成功,根本不 care 输出内容?
- 既要屏幕显示又要存文件:用
tee,例如ping -c 3 google.com | tee ping.log—— 输出实时打屏,同时落盘 - 完全丢弃输出(比如 cron 任务不想发邮件):
command > /dev/null 2>&1,不是/dev/zero,也不是空字符串 - 管道里混用重定向容易出错:
curl https://api.example.com | grep "ok" > result.txt实际是把grep的结果写入result.txt,curl的原始响应根本没进文件——真要存原始响应,得curl https://api.example.com > result.txt
最常被忽略的其实是重定向发生的时机:它在命令执行前就完成文件打开和描述符绑定,所以哪怕命令崩溃、卡死或没输出,文件也早已被创建(或清空)。确认是否真要覆盖、是否需捕获错误、是否需实时反馈——这些判断比语法本身更重要。


















