Shell脚本提取多文件数值累计按父目录输出的问题排查
问题根源
你的脚本出问题主要是两个原因:
- 子shell变量作用域问题:管道符
|后面的括号内容会在独立的子shell中运行,你在里面修改的sum变量不会同步到父shell;同时你最后basename的用法错误,basename是用来取路径的文件名部分,不是用来打印拼接内容的。 - count值异常风险:如果grep匹配到多个结果、或者匹配为空时,
$((sum + count))会直接报语法错误,同时grep的异常输出会直接打在控制台,就是你看到的到处打印count的情况。
修正后的完整脚本
#!/bin/bash shopt -s nullglob # 匹配不到文件时不会返回通配符本身 # 遍历所有Parent目录 for dir in ./[Pp]arent*/; do [ -d "$dir" ] || continue sum=0 # 获取该Parent下最新的时间戳子目录(倒序排序取第一个) latest_subdir=$(find "$dir" -maxdepth 1 -type d | sort -r | head -n 1) if [ -z "$latest_subdir" ] || [ ! -d "$latest_subdir" ]; then echo "$(basename "$dir"): 0(无有效子目录)" continue fi # 遍历所有report.md提取数值累加 while IFS= read -r report_file; do count=$(grep -ohP '(?<=\*)\d+(?=\*+ number of things)' "$report_file" 2>/dev/null | head -n 1) # 只对匹配到的纯数字做累加,避免空值/非数字报错 if [[ "$count" =~ ^[0-9]+$ ]]; then sum=$((sum + count)) fi done < <(find "$latest_subdir" -type f -iname '*report.md') # 打印父目录对应的累计值 echo "$(basename "$dir"): $sum" done
关键修改说明
- 去掉了管道后的子shell结构,改用进程替换
< <(command)的方式给while循环喂输入,所有变量修改都在当前shell生效,不会出现sum累加失效的问题 - 增加了count值的合法性校验,只有匹配到纯数字才会执行累加,避免空值、非数字值导致的语法错误
- 修正了结果打印逻辑,直接输出父目录名称和对应的累加值
- 增加了异常场景兼容:没有有效子目录、找不到report.md、grep匹配不到结果的场景都不会报错
内容的提问来源于stack exchange,提问作者Izak Joubert
相关产品推荐
相关产品推荐

