Bash脚本合并同前缀文件遇大文件量卡顿,求排查循环问题
批量合并同前缀文件的Bash脚本优化方案
问题根源
处理20k文件时速度骤降,大概率是因为脚本采用了O(n²)时间复杂度的低效逻辑——比如每次循环都重复扫描整个目录,或者反复处理已合并完成的文件,导致随着文件数量增加,耗时呈指数级增长。
优化思路
核心是只遍历目录一次,按前缀分组处理,避免重复扫描和无效操作:
- 一次性提取所有文件的前4位前缀,去重得到唯一前缀列表
- 针对每个前缀,一次性合并所有匹配的文件
- 减少不必要的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
相关产品推荐
相关产品推荐

