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

Bash脚本合并同前缀文件遇大文件量卡顿,求排查循环问题

批量合并同前缀文件的Bash脚本优化方案

问题根源

处理20k文件时速度骤降,大概率是因为脚本采用了O(n²)时间复杂度的低效逻辑——比如每次循环都重复扫描整个目录,或者反复处理已合并完成的文件,导致随着文件数量增加,耗时呈指数级增长。

优化思路

核心是只遍历目录一次,按前缀分组处理,避免重复扫描和无效操作:

  1. 一次性提取所有文件的前4位前缀,去重得到唯一前缀列表
  2. 针对每个前缀,一次性合并所有匹配的文件
  3. 减少不必要的I/O操作和重复判断

优化后的脚本示例

#!/bin/bash

# 仅处理当前目录下的普通文件,排除子目录
shopt -s nullglob  # 避免匹配不到文件时出现通配符本身

# 收集所有文件的前4位前缀,去重排序
prefixes=$(for file in *; do
    if [ -f "$file" ]; then
        printf "%s\n" "${file:0:4}"
    fi
done | sort | uniq)

# 遍历每个唯一前缀,合并对应文件
for prefix in $prefixes; do
    # 用数组存储当前前缀的所有文件
    files=("$prefix"*)
    file_count=${#files[@]}

    # 只有文件数大于1时才执行合并
    if [ "$file_count" -gt 1 ]; then
        # 合并到前缀命名的文件(可自定义后缀)
        cat "${files[@]}" > "${prefix}_merged.txt"
        # 可选:合并完成后删除原文件,根据需求注释/取消注释
        # rm "${files[@]}"
        echo "完成合并:前缀 $prefix,共 $file_count 个文件"
    fi
done

原脚本常见低效点(对照自查)

如果你的原脚本是类似下面的写法,必然会在大文件量下卡顿:

# 低效写法示例(请勿使用)
for file in *; do
    prefix="${file:0:4}"
    # 每个文件都触发一次全目录扫描,20k文件会重复扫描20k次
    for match_file in "$prefix"*; do
        if [ "$match_file" != "$file" ]; then
            cat "$match_file" >> "${prefix}_merged.txt"
            rm "$match_file"
        fi
    done
done

这种写法的问题:

  • 每次循环都重新扫描整个目录,时间复杂度从O(n)变成O(n²)
  • 已删除的文件还会被后续循环反复匹配,做无用功
  • 多次打开/关闭合并文件,增加I/O开销

额外优化建议

  • 开启nullglob选项:避免当某个前缀没有匹配文件时,通配符$prefix*被当作字符串处理
  • 用双引号包裹所有变量:防止文件名包含空格、换行等特殊字符时出错
  • 若需处理子目录,可改用find命令收集文件:find . -maxdepth 1 -type f -printf "%f\n"(仅当前目录)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 04:22:46