如何基于Linux cmp命令计算文件差异百分比?附脚本需求
当然可以实现!我们可以通过cmp -l统计两个文件的逐字节差异,再结合文件大小的差值(处理长度不同的情况),最终计算出基于较大文件总字节数的差异百分比。下面是经过边界情况处理的Shell脚本片段:
#!/bin/bash # 检查输入参数数量 if [ $# -ne 2 ]; then echo "用法: $0 <文件路径1> <文件路径2>" exit 1 fi file_a="$1" file_b="$2" # 验证输入是否为有效文件 for target_file in "$file_a" "$file_b"; do if [ ! -f "$target_file" ]; then echo "错误: '$target_file' 不是有效的普通文件或不存在" exit 1 fi done # 获取两个文件的字节大小(Linux环境下的stat用法) size_a=$(stat -c "%s" "$file_a") size_b=$(stat -c "%s" "$file_b") # 确定基准大小:取两个文件中较大的字节数 base_size=$(( size_a > size_b ? size_a : size_b )) # 步骤1:用cmp统计逐字节对比的差异数 # cmp -l 会输出每个差异的字节位置和内容,wc -l统计行数即差异字节数;重定向错误输出避免文件长度不同时的提示 cmp_diff_count=$(cmp -l "$file_a" "$file_b" 2>/dev/null | wc -l) # 步骤2:计算文件长度差异的字节数(较短文件没有的部分全部视为差异) length_diff=$(( size_a > size_b ? size_a - size_b : size_b - size_a )) # 总差异字节数 = 逐字节差异数 + 长度差异数 total_diff_bytes=$(( cmp_diff_count + length_diff )) # 计算差异百分比:用awk处理浮点运算,保留两位小数 diff_percentage=$(echo "$total_diff_bytes $base_size" | awk '{printf "%.2f", ($1/$2)*100}') # 输出结果 echo "=== 文件差异统计 ===" echo "文件A大小: $size_a 字节" echo "文件B大小: $size_b 字节" echo "基准大小(较大文件): $base_size 字节" echo "总差异字节数: $total_diff_bytes" echo "差异百分比: ${diff_percentage}%"
关键细节说明
cmp -l的核心作用:这个参数让cmp逐字节对比两个文件,每发现一个差异就输出一行记录;我们用wc -l统计这些行的数量,得到前N字节(N为较短文件长度)的差异数。- 处理长度不同的边界情况:如果两个文件长度不一样,较短文件没有的那部分字节本质上和另一个文件完全不同,所以需要把长度差加到总差异数里——比如你提到的a1.jpg(1000字节)和a2.jpg(1021字节),后面的21字节会被直接计入差异。
- 浮点运算处理:Shell本身仅支持整数运算,所以用
awk来完成百分比的计算和格式化,确保结果保留两位小数,可读性更好。 - 兼容性提示:脚本中用
stat -c "%s"获取文件大小是Linux标准用法;如果是BSD/macOS环境,需要将stat命令改为stat -f "%z"。
内容的提问来源于stack exchange,提问作者ScriptWriter
相关产品推荐
相关产品推荐

