Text processing
cmp
Compare two files byte by byte and report the first difference, or just whether they differ.
cmp [OPTION...] FILE1 [FILE2 [SKIP1 [SKIP2]]]
cmp compares two files as raw bytes and stops at the first byte that differs. It does not
care about lines or text, which makes it the right tool for binaries (images, archives,
compiled programs) and the fastest way to answer "are these two files identical?".
Its output is one line naming the byte and line number of the first difference. With -s it
prints nothing and you use the exit status: 0 identical, 1 different, 2 trouble. If you
need to see what changed in a text file, use diff; to compare files you cannot put side
by side (on different machines), compare their sha256sum hashes instead.
Examples
Find the first difference between two files
sed 's/fix logout/fix signup/' todo.txt > todo2.txt
cmp todo.txt todo2.txt
todo.txt todo2.txt differ: byte 40, line 4
cmp stops at the first differing byte and reports its position counted from 1, along with the line it is on. The exit status is 1.
Identical files print nothing
cp photos/beach.png copy.png
cmp photos/beach.png copy.png && echo "identical"
identical
When the files match, cmp is silent and exits with 0. It works the same on images or any other binary file.
Test for equality in a script with -s
if cmp -s photos/beach.png photos/forest.png; then echo same; else echo "different (status $?)"; fi
different (status 1)
-s suppresses all output, so only the exit status speaks. Inside the else branch $?
still holds cmp's status, 1.
Compare binary files
cmp photos/beach.png photos/forest.png
photos/beach.png photos/forest.png differ: byte 19, line 3
Both are PNG images, so the first bytes (the PNG signature and header) are the same. The first difference is inside the header, where the image dimensions are stored. The "line" number counts newline bytes, which means little in binary data.
List every differing byte with -l
printf 'hello world\n' > a.txt
printf 'hallo world!\n' > b.txt
cmp -l a.txt b.txt
cmp: EOF on a.txt after byte 12 2 145 141 12 12 41
-l prints every difference as the byte position and the two values in octal: 145 is
e, 141 is a. Position 12 is where b.txt has ! (41) and a.txt its newline
(12). After that a.txt ends while b.txt has one more byte, which cmp reports as EOF
on stderr; that note shows up first only because stderr is not buffered.
Show the differing characters with -b
sed 's/fix logout/fix signup/' todo.txt > todo2.txt
cmp -b todo.txt todo2.txt
todo.txt todo2.txt differ: byte 40, line 4 is 154 l 163 s
-b adds the two differing bytes, both in octal and as characters, so you can see the l
of logout against the s of signup.
Detect when one file is a prefix of the other
head -3 todo.txt > short.txt
cmp todo.txt short.txt
cmp: EOF on short.txt after byte 35, line 3
When the files agree until one runs out, cmp reports EOF on the shorter one. That is still a difference, so the status is 1.
Compare only the first bytes with -n
cmp -n 8 photos/beach.png photos/forest.png && echo "same 8-byte signature"
same 8-byte signature
-n 8 stops after eight bytes. Every PNG file starts with the same eight-byte signature,
so both images match within that range.
A missing file is status 2
cmp todo.txt nosuch.txt
cmp: nosuch.txt: No such file or directory
Status 2 means cmp could not compare, which a script should treat differently from "the files differ".
Common pitfalls
cmpstops at the first difference. To count or list all of them, use-l(bytes) ordiff(lines).Treating any non-zero status as "different" hides errors like a missing file. Check for 1 and 2 separately.
Line endings count: a file saved with CRLF and its LF copy differ at the first line ending even though they look the same.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
-s,-land the exit statuses are POSIX and behave the same everywhere.-b,-nand-iare extensions; the BSD and macOS cmp have their own set, so check the local man page before using them in portable scripts.
Options worth knowing
A selection, described in our own words. For the full list, see cmp(1) or cmp --help.
| Option | What it does |
|---|---|
-s, --quiet | Print nothing; report only through the exit status. |
-l, --verbose | List the position and octal values of every differing byte. |
-b, --print-bytes | Also print the differing bytes. |
-n, --bytes LIMIT | Compare at most LIMIT bytes. |
-i, --ignore-initial SKIP | Skip the first SKIP bytes of both files (or SKIP1:SKIP2). |
Related
diffCompare two files or directories line by line and print the changes that turn one into the other.sha256sumCompute SHA-256 checksums of files, or verify files against a list of checksums with -c.md5sumCompute or verify MD5 checksums; fine for spotting accidental changes, not for security.xxdMake a hex dump of a file, or turn a hex dump back into binary with -r.odDump a file's bytes as octal, hex, decimal or characters, to see exactly what it contains.- Exit codesWhat exit statuses mean, how $? works, the reserved values 126, 127 and 128+N, PIPESTATUS, and how to choose codes for your own scripts.