批量比对不同目录下同名.cfg文件的Bash脚本问题
批量比对两个目录下同名.cfg文件的解决方案
场景说明
你有PROD/Today和PROD/Yesterday两个目录,各自包含100+名称完全相同的.cfg格式文件。单个文件比对的命令可正常执行:
diff PROD/Today/Core.cfg PROD/Yesterday/Core.cfg > PROD/Changes/delta.txt
但批量循环的写法出现问题,以下是错误分析和修正方案:
错误写法分析
第一种循环写法
for i in PROD/Today/*.cfg; do diff PROD/Today/$i PROD/Yesterday/$i > PROD/Changes/delta.txt
- 核心问题:
$i已经是完整路径(如PROD/Today/file.cfg),拼接PROD/Today/后会生成无效路径PROD/Today/PROD/Today/file.cfg - 额外问题:所有比对结果都会覆盖到同一个
delta.txt,无法区分不同文件的差异
第二种写法
find . -maxdepth 1 -type f -name '*.cfg' | while read -r file; do file=$(basename $file) diff PROD/Today/$file PROD/Yesterday/$file > PROD/Changes/$file_delta.txt done
- 问题1:
find . -maxdepth 1仅查找当前目录下的文件,而你的.cfg文件在PROD/Today目录中,导致file变量为空,出现PROD/Yesterday/.cfg: No such file or directory错误 - 问题2:
$file_delta.txt的变量语法错误,shell会将file_delta视为一个未定义的变量,最终输出文件名变为.txt
正确解决方案
方案一:使用for循环(推荐)
先确保输出目录存在,然后遍历PROD/Today下的.cfg文件,提取文件名后比对:
# 确保Changes目录存在,不存在则创建 mkdir -p PROD/Changes for cfg_file in PROD/Today/*.cfg; do # 提取不带路径的文件名 filename=$(basename "$cfg_file") # 比对同名文件,输出到对应delta文件 diff "$cfg_file" "PROD/Yesterday/$filename" > "PROD/Changes/${filename}_delta.txt" done
- 注意:用双引号包裹变量,避免文件名包含空格或特殊字符时出错
- 可选优化:如果只想保留有差异的文件,可修改为:
mkdir -p PROD/Changes for cfg_file in PROD/Today/*.cfg; do filename=$(basename "$cfg_file") output_file="PROD/Changes/${filename}_delta.txt" # 仅当存在差异时才生成文件,无差异则删除空文件 if diff "$cfg_file" "PROD/Yesterday/$filename" > "$output_file"; then rm "$output_file" fi done
方案二:使用find命令
指定正确的查找路径,修正变量语法:
mkdir -p PROD/Changes find PROD/Today -maxdepth 1 -type f -name '*.cfg' | while read -r cfg_file; do filename=$(basename "$cfg_file") diff "$cfg_file" "PROD/Yesterday/$filename" > "PROD/Changes/${filename}_delta.txt" done
内容的提问来源于stack exchange,提问作者bgorton
相关产品推荐
相关产品推荐

