You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效合并目录下所有文件的第4列?

高效合并多文件指定列的解决方案

问题背景

需要合并目录下400个各含50万行的制表符分隔文件的第4列,要求列依次向右追加,for循环处理速度过慢。

示例输入(三个文件)

# file1内容
col1	col2	col3	col4	col5
a	0	0	-1	0.001
b	1	0	2	0.004
c	2	0	3	0

# file2内容
col1	col2	col3	col4	col5
c	2	0	-9	0.004
s	1	0	5	0.002
d	3	0	3	0.4

# file3内容
col1	col2	col3	col4	col5
r	2	1	0	0.4
j	1	1	1	0.2
r	3	1	2	0.1

期望输出

file1	file2	file3
-1	-9	0
2	5	1
3	3	2

你遇到的问题

你尝试先将文件转为CSV格式:

for file in $(ls); do awk '{$1=$1}1' OFS=',' ${file} > ${file}.csv; done

再执行合并命令:

eval paste -d, $(printf "<(cut -d, -f4 %s) " *.csv)

但触发错误:paste: /dev/fd/19: Too many open files——这是因为paste通过进程打开了太多文件描述符,超过了系统限制。

解决方案:用awk直接处理原文件

不需要转格式,用awk一次性处理所有文件,既高效又能避开文件描述符限制:

awk -F'\t' '
    BEGIN {
        # 收集所有输入文件名
        for (i=1; i<ARGC; i++) files[i] = ARGV[i]
        ARGC = 1  # 阻止awk默认遍历文件,后续手动处理
    }
    FNR == 1 { next }  # 跳过每个文件的表头行
    {
        # 按行号和文件索引存储第4列内容
        arr[FNR][ARGIND] = $4
        if (FNR > max_row) max_row = FNR
    }
    END {
        # 输出表头(所有文件名)
        for (i=1; i<=length(files); i++) {
            printf "%s%s", files[i], (i==length(files)?"\n":"\t")
        }
        # 逐行输出各文件的第4列
        for (row=2; row<=max_row; row++) {
            for (i=1; i<=length(files); i++) {
                printf "%s%s", arr[row][i], (i==length(files)?"\n":"\t")
            }
        }
    }
' *.tsv  # 替换为你的实际文件后缀,比如*.txt或直接用*匹配所有目标文件

方案优势

  1. 无需格式转换:直接处理原制表符分隔文件,节省磁盘空间和转换时间
  2. 高效低耗:awk仅遍历所有文件一次,按行存储数据,内存占用可控
  3. 避免系统限制:不会像paste那样打开大量进程导致文件描述符耗尽
  4. 兼容特殊文件名:即使文件名含空格或特殊字符也能正常处理(比你之前用ls的循环更可靠)

内容的提问来源于stack exchange,提问作者Caterina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 19:55:36