Generate: md5sum file.iso > file.iso.md5. Verify: md5sum -c file.iso.md5. That is the whole mechanic, and it answers exactly one question: did this file arrive without being corrupted? It does not answer “has anyone tampered with this file” — MD5 has not been able to answer that since 2004. If the checksum is there to prove authenticity, use sha256sum file.iso instead; the workflow is identical.
RFC 6151 draws the line in two sentences: “MD5 is no longer acceptable where collision resistance is required such as digital signatures”, but “Where the MD5 checksum is used inline with the protocol solely to protect against errors, an MD5 checksum is still an acceptable use.” Catching a truncated download is the second thing. Proving a publisher signed a file is the first. And when a checksum tells you two files differ, it cannot tell you where — diff prints the differing lines, cmp the first differing byte. A live demonstration of two different files sharing one MD5 — run, with output — is on the Windows checksum page; there is no point in printing it twice.
What was executed: everything below ran on macOS 26.6 (arm64) against GNU coreutils 9.11 installed from Homebrew — the same md5sum a Linux distribution ships — and against Apple’s separate /sbin/md5sum. Output is pasted unedited.
The failure worth knowing: md5sum -c can exit 0 having verified nothing
A checksum file that md5sum cannot parse is not the same thing as a checksum that matched, and the two are easy to confuse in a script. GNU treats it as an error:
$ md5sum --version | head -1
md5sum (GNU coreutils) 9.11
$ printf 'this is not a checksum file\n' > junk.txt
$ md5sum -c junk.txt
md5sum: junk.txt: no properly formatted checksum lines found
rc=1
$ : > empty.md5
$ md5sum -c empty.md5
md5sum: empty.md5: no properly formatted checksum lines found
rc=1
The coreutils manual matches: the exit status is nonzero if any file cannot be opened, if checksums mismatch, or “if no valid line is found.” Good. Now the same two files through Apple’s md5sum, which is a different program that happens to share the name:
$ /sbin/md5sum --version | head -1
md5sum (Darwin) 1.0
$ /sbin/md5sum -c junk.txt
md5sum: WARNING: 1 line is improperly formatted
rc=0
$ /sbin/md5sum -c empty.md5
rc=0
Silence, and exit 0. A deploy script written as md5sum -c sums.md5 && install installs. Adding --strict --warn does not help — Apple’s build still exits 0 on the empty file. If your script has to run on both, do not rely on the exit code alone; check the file yourself first:
grep -qE '^[0-9a-fA-F]{32}[ *]|^MD5 \(' sums.md5 || { echo "no checksum lines in sums.md5" >&2; exit 1; }
md5sum -c sums.md5
shasum, which is the Perl script both systems ship, gets this right on its own — another reason to prefer it: shasum: empty.md5: no properly formatted SHA checksum lines found, exit 1. Whether your own md5sum exits 0 on a junk file or an empty checksum file is what generate-md5-checksum.sh tests directly; a case that needs GNU coreutils or Apple’s binary is skipped, not failed, when that binary is missing.
Line endings and piped downloads
Tested, line endings are no longer a cause of no properly formatted md5 checksum lines found under GNU md5sum. A checksum file written on Windows, CRLF confirmed with od, verifies cleanly:
$ od -c crlf.md5 | tail -2
0000040 a . t x t \r \n
0000051
$ md5sum -c crlf.md5
a.txt: OK
rc=0
The CR does bite on macOS, and the symptom is nothing like that error — it is a file-not-found for a file that plainly exists:
$ /sbin/md5sum -c crlf.md5
md5sum: a.txt\r: No such file or directory
rc=1
Download-and-verify in one command cannot work as written:
curl -LJO http://example.com/filename.tar.gz | tee filename.tar.gz | md5sum -c checksumfile.md5
curl -O writes the body to a file, not to stdout. Run against a real URL here, 14662 bytes landed in the file and 0 bytes came out of the pipe, so tee creates an empty filename.tar.gz. And md5sum -c FILE ignores stdin entirely — piping garbage into it changes nothing, it still reads the named file and reports a.txt: OK. Download first, verify second.
md5sum does exist on macOS now, and it is not GNU’s
The standard advice that macOS has md5 but no md5sum is out of date on macOS 26.6. Both are present, and they are literally the same binary — note the identical inode:
$ ls -li /sbin/md5 /sbin/md5sum /sbin/sha256sum
1152921500312571475 -rwxr-xr-x 6 root wheel 136288 /sbin/md5
1152921500312571475 -rwxr-xr-x 6 root wheel 136288 /sbin/md5sum
1152921500312571475 -rwxr-xr-x 6 root wheel 136288 /sbin/sha256sum
Three output formats, one digest. Only the middle one is what a Linux .md5 file contains — hash, two spaces, filename:
$ md5 a.txt
MD5 (a.txt) = b1946ac92492d2347c6235b4d2611184
$ md5 -r a.txt
b1946ac92492d2347c6235b4d2611184 a.txt
$ md5sum a.txt
b1946ac92492d2347c6235b4d2611184 a.txt
In practice both implementations are lenient about the separator — a single space and the BSD MD5 (file) = … tagged form both verified OK under GNU coreutils 9.11 here. What neither will forgive is a wrong hash, which is the only thing you actually wanted checked.