Unix下join与cat命令的输入重定向及进程替换使用疑问
两类重定向的行为差异与使用规则
为什么cat <file1 <file2仅输出World
<文件路径形式的普通输入重定向,核心作用是将指定文件的内容绑定到进程的标准输入(STDIN,即0号文件描述符)上。- shell处理同一文件描述符的多重输入重定向时,会按书写顺序执行绑定操作,后一次绑定会直接覆盖前一次的绑定关系,不会自动累加读取多个文件的内容。
- 因此
cat <file1 <file2的实际执行逻辑为:- 先将STDIN绑定到file1的内容;
- 紧接着将STDIN重新绑定到file2的内容,完全覆盖此前对file1的关联;
- cat默认仅从STDIN读取内容,最终就只会输出file2中的World。
- 补充对比:直接运行
cat file1 file2可以正常拼接输出Hello和World,是因为此时file1、file2是作为位置参数传给cat,cat会将每个参数识别为独立的待读取文件路径,按顺序读取输出,和重定向绑定STDIN的逻辑完全不同。
join示例中的重定向为什么没有覆盖问题
- join命令示例里出现的
<(sort -k 2 wine.txt)、<(sort reviews.txt),并非普通输入重定向,而是bash支持的进程替换语法。 - 进程替换的底层实现逻辑是:shell为括号内的命令单独创建独立的临时管道,生成一个类似
/dev/fd/xxx的特殊临时文件路径,把这个路径作为普通位置参数传给外层的join命令,全程不会占用、覆盖外层命令的STDIN绑定。 - 对应命令拆解后的实际传参逻辑等价于:
join -1 2 -2 1 排序后wine的临时路径 排序后reviews的临时路径。 - join本身的工具设计就是读取两个指定路径的内容,按指定列做关联匹配,因此不存在多重重定向的覆盖问题,能正常输出关联后的结果。
重定向使用的核心规则
- 普通输入重定向(
<文件路径)规则:- 作用目标是进程的文件描述符(默认绑定STDIN),不会为命令生成独立的输入路径参数;
- 同一文件描述符被多次绑定时,后绑定的输入源会完全替代之前的输入源,没有自动累加的效果;
- 若需要让支持多文件读取的命令同时拿到多个输入,更推荐直接把文件路径作为位置参数传递;如果一定要通过重定向实现拼接效果,可以搭配进程替换,比如
cat <(cat file1) <(cat file2)——本质是把两个临时管道路径作为参数传给cat,cat会依次读取两个流的内容,最终得到拼接输出。
- 进程替换(
<(命令))规则:- 本质是生成独立的临时输入路径占位符,不属于修改文件描述符绑定的重定向操作;
- 多个进程替换会生成多个独立的临时路径,全部作为位置参数传递给外层命令,不存在互相覆盖的问题,非常适合给需要读取多个文件路径作为输入的命令(比如join)提供动态生成的输入源。
内容的提问来源于stack exchange,提问作者laurent01
相关产品推荐
相关产品推荐

