TIL:用 cmp 在 Shell 脚本中做逐字节文件比较
原文标题:TIL: cmp: Fast Byte-by-Byte File Comparison for Shell Scripts
在 Shell 脚本里判断两个文件是否相同,可以用 cmp 替代 diff:cmp 逐字节比较并在首个不匹配处停止,即使文件达到 GB 级也能在毫秒内完成,而 diff 需要逐行解析全文。cmp 的 -s 静默模式通过退出码返回结果:0 表示文件相同,1 表示不同,2 表示文件缺失或不可读。cmp 适合二进制文件和自动化脚本,POSIX 环境默认自带。
当前语言的正文正在等待翻译,暂时显示原文。
October 4, 2026 2 min read
Today I stopped using diff to check whether two files match in shell scripts.
My old default check was diff -q file1 file2 > /dev/null. That command solves a different problem. diff parses text line by line to calculate edit hunks. On large disk images, database dumps, or compiled binaries, diff reads entire files and consumes unnecessary CPU cycles.
For a boolean equality check, cmp reads byte by byte and halts at the first mismatch.
The Basic Command
Running cmp without flags prints the first point of divergence:
cmp config-old.json config-new.jsonIf the files match, cmp produces no output. If they differ, it pinpoints the exact byte offset and line:
config-old.json config-new.json differ: byte 25, line 3Because cmp halts at the first mismatch, it finishes in milliseconds even on gigabyte-sized files.
The Shell Script Pattern
The -s (silent) flag suppresses standard output and error streams. The command exits with three status codes for shell conditions:
0: Files are identical1: Files differ2: Trouble encountered (file missing or unreadable)
if cmp -s config.new /etc/app/config.json; then
echo "Configuration unchanged. Skipping reload."
else
echo "Configuration changed. Applying update..."
cp config.new /etc/app/config.json
systemctl restart app
fiThe if block checks the exit code. You drop boilerplate redirects like > /dev/null 2>&1.
cmp vs diff
| Command | Comparison Method | Halts At | Best For |
|---|---|---|---|
cmp | Byte by byte | First mismatch | Equality checks, binary files, shell automation |
diff | Line by line | End of file | Reviewing human-readable text edits |
Quick Reference
| Flag | Purpose | Example |
|---|---|---|
-s | Run silent and return an exit code without output | cmp -s file1 file2 |
-l | Print byte offset and differing octal values | cmp -l file1 file2 |
-b | Print differing bytes as readable characters | cmp -b file1 file2 |
-n N | Compare at most N bytes | cmp -n 1024 disk1.img disk2.img |
Common Workflows
- Backup validation: Verify that a restored database dump matches the original byte for byte:
cmp -s db-backup.sql /mnt/storage/db-backup.sql - Binary artifact checks: Verify that firmware images or compiled binaries match upstream builds:
cmp app-linux-x64 dist/app-linux-x64 - Build pipeline triggers: Prevent downstream rebuild steps by checking if generated asset files changed before writing them.
What I Learned
cmphalts at the first mismatch, leaving the rest of the file unread.- The
-sflag turnscmpinto a boolean test for shell scripts. - The command compares binary assets where
diffissues warnings or chokes on null bytes. - Exit code
2flags missing or inaccessible files, separating system errors from content diffs. - POSIX environments include
cmpby default, requiring no third-party package.
来源:Kondasamy Jayaraman · Engineering Blog · kondasamy.com