This post was originally published on go2linux.org. The domain is no longer mine, but I am the original author. I am republishing it here on garron.me with corrections and improvements.
I once had to move a big .tar.gz file from one FTP server to another, passing through my PC. After uploading it to the second server it turned out to be corrupt, and the copy on my desktop had the same error. If I had checked the file when it arrived on my PC, I would have saved the time of the second transfer.
A checksum solves that. md5sum reads a file and prints a short fingerprint of its contents. If a single bit changes, the fingerprint changes. Calculate it on both ends, compare, and you know whether the copy is identical.
Checksum of a file
md5sum backup.tar.gz
bce4769e984bcb13961eb7a149038c50 backup.tar.gz
The output is the hash, two spaces, and the file name. Run the same command on the other machine and compare the hashes. Several files can be given at once:
md5sum *.iso
Create a checksum file and verify it
Comparing 32 characters by eye is error prone. Save the output to a file instead:
md5sum backup.tar.gz > backup.tar.gz.md5
Move both files to the destination, and there run md5sum with -c (check):
md5sum -c backup.tar.gz.md5
backup.tar.gz: OK
When the file is damaged:
backup.tar.gz: FAILED
md5sum: WARNING: 1 computed checksum did NOT match
The exit status is 0 only when every file matches, so it works in scripts:
md5sum -c --status backup.tar.gz.md5 && echo "copy is good"
A whole directory
Use find to run md5sum on every regular file below the current directory. Write the list outside the directory, so it does not end up containing itself:
cd /srv/photos
find . -type f -exec md5sum {} + > ../photos.md5
The result is one line per file:
bce4769e984bcb13961eb7a149038c50 ./xp15.png
b9a474939619ce6717fc87b1d5873f7d ./office6.png
e3e202d0be6e4bd4b449537c0819b851 ./2024/ubuntu7.png
After copying the directory, go to the copy and check it against the list:
cd /mnt/backup/photos
md5sum -c --quiet ../photos.md5
--quiet prints only the files that fail, which is what you want with thousands of files. No output means everything matched. Files that exist in the list but are missing in the copy are reported as errors; files that are only in the copy are not noticed, because the list does not know about them.
Use sha256sum when it matters
MD5 is fine for the case above: detecting accidental damage during a transfer or on a failing disk. It is not safe against someone who alters a file on purpose. Producing two different files with the same MD5 hash has been practical for years.
For anything related to security, use sha256sum. It is in the same package (coreutils) and takes exactly the same options:
sha256sum backup.tar.gz > backup.tar.gz.sha256
sha256sum -c backup.tar.gz.sha256
sha1sum, sha512sum and b2sum work the same way.
Verify a downloaded ISO
Distributions publish a file with the hashes of all their images, usually named SHA256SUMS. Download it to the same directory as the image and run:
sha256sum -c --ignore-missing SHA256SUMS
debian-13.1.0-amd64-netinst.iso: OK
--ignore-missing skips the images listed in the file that you did not download.
If the site only shows the hash on a web page, build the line yourself. Mind the two spaces between hash and file name:
echo "PASTE_THE_HASH_HERE debian-13.1.0-amd64-netinst.iso" | sha256sum -c -
A checksum downloaded from the same server as the file proves the download is complete, not that it is authentic: whoever could replace the image could replace the checksum as well. For that, distributions sign the checksum file with GPG, and you verify the signature with gpg --verify.
Compare two files quickly
md5sum file1 file2
Same hash, same contents. To find every duplicate in a directory, sort by hash and print the repeated ones:
find . -type f -exec md5sum {} + | sort | uniq -w32 -D
On macOS
macOS does not ship md5sum. The equivalents are md5 and shasum -a 256. See md5sum on Mac OS X.
See also
man md5sum and man sha256sum — full reference.