cmp — Compare two files byte-by-byte and report the first difference across all 5 shells
Equivalents in every shell
cmp a.bin b.binSilent on identical files (exit 0); prints `a.bin b.bin differ: byte N, line M` on first byte mismatch (exit 1); errors out on read failure (exit ≥ 2). `-l` lists EVERY differing byte (not just the first); `-s` (silent) suppresses output for use in shell tests like `cmp -s a b && echo "same"`.
cmp a.bin b.binSame external `cmp` (POSIX). macOS BSD cmp has the same `-l` and `-s` flags as GNU coreutils. Differences are marginal — GNU adds `--print-bytes` (`-b`) which shows the differing byte values in addition to offsets; BSD cmp lacks `-b`.
cmp a.bin b.binSame external. Fish's exit-code idiom — `if cmp -s a b; echo same; else; echo differ; end` — reads cleaner than bash's `&&`/`||` chain. Fish does NOT auto-export `$status` to subshell positions, so always check explicitly.
(Get-FileHash a.bin).Hash -eq (Get-FileHash b.bin).Hashpwsh has no byte-by-byte file comparator. `Get-FileHash` (SHA-256 default) gives a same/differ verdict but not WHERE the difference is. For "where does it differ" use `Compare-Object` on `[byte[]]` arrays, or shell out to `fc /b a b` (cmd.exe binary compare). For large files, `Get-FileHash` is fastest (single-pass hash).
fc /b a.bin b.bin`fc /b` (binary mode) is cmd.exe's built-in byte comparator — outputs each differing byte offset + values in hex. Without `/b`, fc does line-mode comparison (defaults to text). Always pass `/b` for binary files; `/n` for line numbers; `/c` for case-insensitive text.
Worked examples
Silent test: did the two files match?
cmp -s a.bin b.bin && echo "identical" || echo "differ"if ((Get-FileHash a.bin).Hash -eq (Get-FileHash b.bin).Hash) { "identical" } else { "differ" }fc /b a.bin b.bin > nul && echo identical || echo differList EVERY differing byte (not just the first)
cmp -l a.bin b.binCompare-Object ([IO.File]::ReadAllBytes('a.bin')) ([IO.File]::ReadAllBytes('b.bin')) -IncludeEqual:$falsefc /b a.bin b.binCompare two file streams (e.g. from network) without writing to disk
cmp <(curl -s https://a.example.com/file) <(curl -s https://b.example.com/file)(Invoke-WebRequest a -OutFile a.tmp; Invoke-WebRequest b -OutFile b.tmp; (Get-FileHash a.tmp).Hash -eq (Get-FileHash b.tmp).Hash)Gotchas
- Exit codes are documented but easy to misread: `0` = identical, `1` = differ (NOT an error), `≥ 2` = read / argument error. Scripts that treat non-zero as failure will wrongly report identical-vs-different as a failure — use `cmp -s; case $? in 0) echo same;; 1) echo differ;; *) echo error;; esac`.
- `-l` (list all) without `-b` (print bytes) outputs `byte_offset octal_a octal_b` — OCTAL by default, which surprises everyone (people expect hex or decimal). Use `-b` on GNU cmp for `byte_offset decimal_a "value_a" decimal_b "value_b"` format; BSD cmp has no `-b`.
- `cmp` reads BOTH files in parallel, stopping at the first byte difference (without `-l`). For huge files that differ early, this is fast (no need to read the rest). For huge files that differ LATE (or not at all), it reads both files in full — slower than `Get-FileHash` (which can use hardware-accelerated SHA-NI on x86_64 / ARM crypto extensions for ~10× throughput).
- cmd `fc /b` writes the offset in HEX, but cmp on Linux writes byte-counts in DECIMAL. Cross-comparing tool output is confusing — pick one tool for a script and stick with it.
- Files with one-byte length differences: `cmp` reports `EOF on a.bin after byte N` for the SHORTER file — useful diagnostic. `Get-FileHash` just says "different hash" with no clue about the cause. For length-then-content comparison, `cmp` is more informative.