Bash脚本批量替换异常:多文件无法对应numbers.txt不同数值
解决Bash+gsed批量对应替换子目录文件内容的问题
先理清楚你的核心需求和之前踩过的坑:
你有Parent目录下的Daughter1、Daughter2等一系列子目录,每个子目录里都有一个input文件,所有这些文件里都有固定的旧数字12.345678需要替换。同时你有一个numbers.txt,每行对应一个新数字,要求Daughter1/input用第一行数字,Daughter2/input用第二行数字,以此类推。
之前的尝试存在的问题:
- 第一个脚本用固定
new_number,只能统一替换成同一个值,完全不符合批量对应替换的需求; - 第二个脚本循环里每次用
find Parent/Daughter*匹配所有子目录,导致每一轮循环都会把所有input文件替换成当前行的数字,最终所有文件都会被覆盖成numbers.txt最后一行的内容(你说变成第一行可能是循环只执行了一次,但核心逻辑是错误的); - 你更新后的脚本已经找对了方向——指定单个对应目录,但需要调整序号匹配逻辑,同时加上循环停止的判断条件。
完善后的脚本实现
下面是解决了序号匹配和停止问题的最终脚本:
#!/bin/bash old_number="12.345678" # 先获取所有Daughter子目录并按名称排序,确保顺序和numbers.txt严格对应 mapfile -t dirs < <(find Parent -type d -name "Daughter*" | sort) i=0 while read -r new_num; do # 检查当前序号对应的子目录是否存在,不存在就停止循环 if [[ -z "${dirs[$i]}" ]]; then echo "已处理完所有子目录,提前退出循环" break fi # 用gsed替换对应目录下的input文件 gsed -i -e "s/${old_number}/${new_num}/g" "${dirs[$i]}/input" echo "完成处理:${dirs[$i]}/input → 替换为 ${new_num}" ((i++)) done < numbers.txt # 额外提示:如果numbers.txt行数多于子目录数量,告知剩余未使用的行 if [[ $i -lt $(wc -l < numbers.txt) ]]; then echo "注意:numbers.txt还有 $(( $(wc -l < numbers.txt) - i )) 行数字没有对应的子目录" fi
脚本关键说明
- 子目录排序:用
find结合sort获取所有Daughter*子目录并排序,确保目录顺序和numbers.txt的行顺序完全匹配(比如Daughter1在前,Daughter2在后); - 鲁棒的目录匹配:用数组存储子目录路径,避免手动拼接
Daughter${i}可能出现的序号不匹配问题(比如子目录命名是Daughter0或者不规则命名时,这个方法依然有效); - 循环停止条件:每次循环检查对应索引的目录是否存在,不存在就立即退出,避免无效操作;
- 友好提示:最后检查如果
numbers.txt行数多于子目录数量,给出明确提示,避免遗漏信息。
简化版(适合子目录命名严格规则的场景)
如果你确定子目录严格按照Daughter1、Daughter2...的规则命名,序号从1开始,可以用更简洁的写法:
#!/bin/bash old_number="12.345678" i=1 while read -r new_num; do dir="Parent/Daughter${i}" # 目录不存在就停止循环 if [[ ! -d "${dir}" ]]; then echo "目录 ${dir} 不存在,停止处理" break fi gsed -i -e "s/${old_number}/${new_num}/g" "${dir}/input" ((i++)) done < numbers.txt
内容的提问来源于stack exchange,提问作者Ant
相关产品推荐
相关产品推荐

