diff compares two files line by line and shows what changed. On servers it answers questions like “what did I change in this config?”, “how does this server’s nginx.conf differ from that one?” and “what did the package update change?”.

Unified format: the one to use

diff -u nginx.conf.bak nginx.conf
--- nginx.conf.bak	2026-10-12 09:10:22
+++ nginx.conf	2026-10-14 15:31:07
@@ -12,7 +12,8 @@
     sendfile on;
     tcp_nopush on;
-    keepalive_timeout 65;
+    keepalive_timeout 30;
+    client_max_body_size 64m;
     types_hash_max_size 2048;

How to read it:

  • --- is the old file and +++ is the new one.
  • @@ -12,7 +12,8 @@ — this “hunk” starts at line 12 and covers 7 lines in the old file and 8 in the new.
  • Lines starting with - were removed, lines with + were added, and lines with a space are unchanged context.

This is the same format git diff uses. The default “normal” diff output (12c12, <, >) is harder to read, so get used to -u.

Exit status

diff exits with 0 if the files are identical, 1 if they differ and 2 on errors. Use that in scripts:

if diff -q current.conf expected.conf > /dev/null; then
  echo "unchanged"
fi

-q only reports whether the files differ.

Readable output

diff -u --color=auto a b         # coloured
diff -y a b                      # side by side
diff -y --suppress-common-lines a b
diff -y -W 200 a b               # wider columns

For a nicer experience, vimdiff a b shows files side by side with highlighting. git diff --no-index a b gives git’s colouring and word-level diffs (--word-diff) for files that aren’t in a repository.

Ignore noise

diff -u -w a b            # ignore all whitespace
diff -u -b a b            # ignore changes in the amount of whitespace
diff -u -B a b            # ignore blank lines
diff -u -i a b            # ignore case
diff -u --strip-trailing-cr a b   # ignore Windows vs Unix line endings
diff -u -I '^#' a b       # ignore changed lines that match a regex (comments here)

Compare directories

diff -rq /etc/nginx /backup/etc/nginx       # which files differ or exist only on one side
diff -ru old-site/ new-site/                # full recursive diff
diff -ru -x '*.log' -x 'cache' a/ b/        # exclude patterns

For large trees, rsync -rcn --delete --out-format='%n' a/ b/ is another way to list differences without transferring anything. See rsync.

Compare with command output or a remote file

Process substitution treats command output as a file:

diff -u <(ssh web1 cat /etc/nginx/nginx.conf) <(ssh web2 cat /etc/nginx/nginx.conf)
diff <(sort list1.txt) <(sort list2.txt)
diff -u <(dpkg --get-selections) <(ssh other dpkg --get-selections)   # installed packages

From stdin, use - as one of the filenames:

curl -s https://example.com/robots.txt | diff -u - local-robots.txt

After package upgrades

When apt asks what to do about a modified config file, choose “show the differences”. Later, the distribution’s version is saved as *.dpkg-dist or *.dpkg-new, so you can compare:

diff -u /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-dist

On RHEL-family systems, look for .rpmnew files.

Create and apply patches

diff -u original.conf fixed.conf > fix.patch
patch original.conf < fix.patch           # apply
patch -R original.conf < fix.patch        # revert
patch --dry-run -p1 < changes.patch       # test first

For directories, run diff -ruN old/ new/ > changes.patch and apply it from inside the old directory with patch -p1 < changes.patch. -N treats missing files as empty, so new files are included.

Tool Use
cmp Compare binary files byte by byte
comm Lines common to two sorted files
sha256sum Check whether files are identical across servers
colordiff Coloured diff output
git diff Track config changes over time (etckeeper puts /etc in git)

etckeeper is worth installing on servers. It commits /etc to git automatically on every package change, so git log -p shows exactly what changed and when.

Quick reference

Task Command
Unified diff diff -u a b
Just “differ?” diff -q a b
Side by side diff -y a b
Ignore whitespace diff -uw a b
Directories diff -ru dir1 dir2
Remote vs local diff -u <(ssh h cat f) f
Make patch diff -u a b > p.patch
Apply patch patch a < p.patch

Related: sort and uniq and Git cheat sheet.

  • Linux
  • Command Line
  • Basics