为何Bash中`ls > out | cat < out`仅首次运行有输出?
问题原因与解释
Bash 类 Shell 的行为逻辑
执行ls > out | cat < out时,这类 Shell 会并行启动管道两侧的进程,同时完成所有重定向操作:
- 首先对
out文件执行截断操作(因使用>重定向),无论文件是否存在,都会被清空为 0 字节。 - 同时启动
ls和cat两个进程:ls进程开始向out写入内容cat进程立刻打开out读取内容
- 由于进程并行执行,
cat会先读取到空的out文件(此时ls可能还未完成写入),触发 EOF 后直接退出,后续ls写入的内容无法被cat捕获。 - 首次运行时,
out文件原本不存在,创建文件的过程可能让ls的写入动作稍早于cat的读取,因此能输出结果;但后续运行时,out已存在,截断后直接为空,cat会快速读取空文件退出,导致无输出。
Zsh 的行为逻辑
Zsh 对管道的处理与 Bash 类 Shell 不同,它会先等待管道左侧的命令执行完毕,再启动右侧命令:
- 先执行
ls > out,等ls完全将内容写入out后,再启动cat < out。 - 此时
out已经有完整的ls输出内容,cat读取后自然能正常输出,因此每次运行都有结果。
修复建议
如果要在类 Bash Shell 中实现每次运行都有输出,需要确保ls执行完毕后再启动cat,可以用分号替代管道:
ls > out; cat < out
或者用逻辑与保证执行顺序:
ls > out && cat < out
内容的提问来源于stack exchange,提问作者ZmRR
相关产品推荐
相关产品推荐

