diff file1 file2 # default format
diff -u old.conf new.conf # unified format (what patches and git use)
diff -y --width=160 a b # side by side
diff -w a b # ignore whitespace changes
diff -q dir1 dir2 # only report which files differ
diff -qr dir1 dir2 | sort > diffs.txt # recursive, sorted list of differences
diff -rq --exclude='.git' dir1 dir2
Across hosts¶
Process substitution runs a command on each side and compares the output without temporary files:
diff <(ssh user@host1 'cat /etc/fstab') <(ssh user2@host2 'cat /etc/fstab')
diff -b <(ssh host1 'ls -l /srv/app') <(ssh host2 'ls -l /srv/app') # -b ignores changes in amount of whitespace
# One remote file against a local one
ssh host cat /etc/hosts | diff /etc/hosts -
To compare whole directory trees between hosts, checksum both sides first (find . -type f -exec sha256sum {} + | sort -k2) and diff the lists, or use rsync -avn as a dry run.
"The files differ but I can't see how"¶
Hidden differences are usually whitespace, tabs versus spaces, CRLF versus LF line endings, or non-printing characters. Reveal them:
cat -A file # $ marks line ends, ^I tabs, ^M carriage returns
diff <(cat -A a) <(cat -A b)
In vim, :set list shows tabs and end-of-line markers. Convert line endings with dos2unix.
Produce and apply patches with patch.