Linux cmp命令 详解

cmp命令 用于比较两个文件,逐字节检查差异,特别适合二进制文件的比较。

命令简介

cmp(compare的缩写)命令主要用于:

  • 逐字节比较两个文件的内容
  • 检测文件的第一个差异位置
  • 比较二进制文件和文本文件
  • 验证文件是否完全相同

命令语法

cmp [选项] 文件1 文件2

常用选项

选项 说明
-l, --verbose 显示所有不同的字节
-s, --quiet, --silent 不显示任何输出,只返回退出状态
-i SKIP, --ignore-initial=SKIP 跳过两个文件的前SKIP个字节
-i SKIP1:SKIP2, --ignore-initial=SKIP1:SKIP2 跳过文件1的前SKIP1字节和文件2的前SKIP2字节
-n LIMIT, --bytes=LIMIT 最多比较LIMIT个字节
-b, --print-bytes 显示不同的字节内容
--help 显示帮助信息
-v, --version 显示版本信息

退出状态

cmp命令的退出状态码:

  • 0 - 文件相同
  • 1 - 文件不同
  • 2 - 发生错误(文件不存在、权限问题等)

使用示例

1. 基本文件比较

比较两个文件,显示第一个差异的位置:

cmp file1.txt file2.txt
file1.txt file2.txt differ: byte 15, line 3

输出说明:文件在第15字节(第3行)处开始不同。

2. 静默模式比较

使用静默模式,只通过退出状态判断文件是否相同:

cmp -s file1.txt file2.txt
echo $?
# 输出 1 表示文件不同,0 表示相同

这在脚本中特别有用,可以基于比较结果执行不同操作。

3. 显示所有差异字节

使用 -l 选项显示所有不同的字节:

cmp -l file1.bin file2.bin
15 12 14
20 40 41
25 0 12

输出说明:

  • 第一列:字节位置(十进制)
  • 第二列:文件1的字节值(八进制)
  • 第三列:文件2的字节值(八进制)

4. 显示字节内容和差异

使用 -b 选项显示差异字节的实际内容:

cmp -b file1.txt file2.txt
file1.txt file2.txt differ: byte 15, line 3 is 114 r 115 s

输出说明:在第15字节处,file1.txt是'r'(114),file2.txt是's'(115)。

5. 跳过文件开头部分

跳过文件开头的一定字节后再进行比较:

# 跳过两个文件的前10个字节
cmp -i 10 file1.bin file2.bin

# 跳过file1的前10字节和file2的前20字节
cmp -i 10:20 file1.bin file2.bin

6. 限制比较的字节数

只比较文件的前N个字节:

cmp -n 100 file1.bin file2.bin

这在大文件比较时可以提高效率。

7. 在脚本中使用cmp

在shell脚本中利用退出状态进行条件判断:

#!/bin/bash

if cmp -s "$1" "$2"; then
    echo "文件相同"
else
    echo "文件不同"
fi

8. 结合find命令批量比较

使用find命令查找并比较文件:

# 比较目录中所有.txt文件与备份目录中的对应文件
find . -name "*.txt" -exec cmp -s {} /backup/{} \; -print

与其他比较命令的对比

命令 比较方式 输出格式 适用场景
cmp 逐字节比较 字节位置、差异字节 二进制文件、精确差异定位
diff 行比较 行号、具体差异内容 文本文件、代码比较
comm 行比较(排序文件) 三列输出:唯一行、唯一行、共同行 已排序文件的集合操作
cksum/md5sum 校验和比较 校验和值 文件完整性验证

实际应用场景

1. 二进制文件验证

比较编译后的二进制文件是否相同:

cmp program_v1 program_v2
if [ $? -eq 0 ]; then
    echo "二进制文件相同"
else
    echo "二进制文件有差异"
fi

2. 固件验证

验证固件文件在传输过程中是否损坏:

cmp original_firmware.bin downloaded_firmware.bin

3. 数据恢复验证

验证恢复的数据是否与原始数据一致:

cmp -l original.dat recovered.dat | head -10

4. 加密文件比较

比较加密前后的文件差异(应完全不同):

cmp plaintext.txt encrypted.txt
# 期望输出:文件完全不同

高级用法

1. 比较进程输出

使用进程替换比较两个命令的输出:

cmp <(ls /dir1) <(ls /dir2)

2. 忽略文件头比较

比较跳过特定文件头(如ELF头)的可执行文件:

# 跳过ELF头(通常64字节)
cmp -i 64 program1 program2

3. 批量文件比较脚本

创建脚本批量比较目录中的文件:

#!/bin/bash
# 比较两个目录中的同名文件

dir1="$1"
dir2="$2"

for file in "$dir1"/*; do
    filename=$(basename "$file")
    if [ -f "$dir2/$filename" ]; then
        if ! cmp -s "$file" "$dir2/$filename"; then
            echo "差异文件: $filename"
        fi
    fi
done

注意事项

  • cmp命令对文件大小敏感,如果文件大小不同,会在较小文件结束时报告EOF
  • 对于文本文件,diff命令通常更实用,因为它能显示具体的差异内容
  • 使用 -l 选项比较大型文件时,输出可能会很长
  • cmp比较的是字节内容,不考虑文本文件的编码差异
  • 在比较之前确保文件存在且有读取权限

性能提示

  • 对于大文件,使用 -n 选项限制比较范围可以提高速度
  • 如果只关心文件是否相同,使用 -s 选项避免不必要的输出
  • 在脚本中,先检查文件大小是否相同,可以快速排除明显不同的文件
  • 对于非常大的文件,考虑使用 split 命令分割后再比较

相关命令

  • diff - 逐行比较文本文件
  • comm - 比较两个已排序的文件
  • cksum - 计算文件校验和
  • md5sum - 计算MD5校验和
  • wc - 统计文件字节数、行数等
  • od - 以八进制或其他格式显示文件内容