diff Command Explained

diff Command Explained

diff compares two files and reports exactly what is different between them. It is one of the tools underlying version control, code review, and configuration management, even when you are not directly aware it is running underneath something else.

Basic usage

diff old.conf new.conf
3c3
< max_connections = 100
---
> max_connections = 250
5a6
> enable_cache = true

In this older, default output format, 3c3 means line 3 was changed (c) between the two files, 5a6 means a new line was added (a) after line 5 of the first file, becoming line 6 in the second. Lines starting with < show the original content; lines starting with > show the new content.

Unified diff format: the modern standard

diff -u old.conf new.conf
--- old.conf    2026-07-08 22:00:00
+++ new.conf    2026-07-09 09:00:00
@@ -1,6 +1,7 @@
 server_name example.com
 listen 80
-max_connections = 100
+max_connections = 250
 timeout = 30
+enable_cache = true
 root /var/www/html

Unified diff format (-u) is far more widely used today. Lines prefixed with - were removed, lines prefixed with + were added, and unprefixed lines are unchanged context shown to help you understand where in the file the change occurred. This format is compact, genuinely readable at a glance, and critically, it is the exact format the patch command expects as input, making diff -u and patch a matched pair.

Comparing entire directories

diff -r configs_backup/ configs_current/
diff -r configs_backup/nginx.conf configs_current/nginx.conf
3c3
< max_connections = 100
---
> max_connections = 250

Only in configs_current/: new_service.conf

-r (recursive) extends the comparison to every file across two directory trees at once, reporting per-file differences the same way a single-file comparison would, plus flagging any file that exists in one directory but is entirely missing from the other.

Creating a reusable patch file

diff -u original.conf modified.conf > changes.patch
cat changes.patch

Redirecting a unified diff’s output into a file produces a patch file: a self-contained description of exactly what changed, which can later be applied to another, unmodified copy of the original file using the patch command, reproducing the same edit without manually retyping or copying it.

# Applying it elsewhere later
patch original.conf < changes.patch

Side-by-side comparison

diff -y old.conf new.conf
server_name example.com          server_name example.com
listen 80                          listen 80
max_connections = 100          |   max_connections = 250
timeout = 30                      timeout = 30
                                  >  enable_cache = true

-y displays both files side by side in two columns, with a | marking changed lines and a > marking lines only present in the second file. This can be easier to scan visually for a smaller file, though unified format remains more common for anything meant to be shared, stored, or fed into patch.

Ignoring whitespace differences

diff -b old.conf new.conf     # ignore changes in amount of whitespace
diff -w old.conf new.conf      # ignore ALL whitespace entirely
diff -B old.conf new.conf       # ignore blank line changes

These flags are useful when comparing two files that may have been reformatted (different indentation, trailing spaces, or line endings) without any actual meaningful content change, letting you focus specifically on substantive differences rather than cosmetic ones.

Checking for equality in scripts

if diff -q file1.txt file2.txt > /dev/null; then
  echo "Files are identical"
else
  echo "Files differ"
fi

-q (quiet, or brief) suppresses the detailed line-by-line output and just reports whether the files differ at all, which combined with checking diff’s exit code is a standard, efficient way to test file equality inside a script without needing to parse or discard detailed diff output you do not actually need.

Frequently Asked Questions

What does the diff command do?

diff compares two text files line by line and reports exactly what would need to change to turn one into the other: which lines were added, removed, or modified. It is the standard tool for understanding the difference between two versions of a file, such as an original configuration and an edited version.

What is the unified diff format and why is it the standard?

Unified diff format, produced with diff -u, shows changes with a few lines of surrounding context on each side, and marks added lines with a leading + and removed lines with a leading -, all within a single combined view. It is the standard format because it is compact, human-readable, and is also the exact format the patch command expects as input, making it the bridge between “here is what changed” and “apply this change elsewhere.”

How do I compare two entire directories instead of two individual files?

Use the -r (recursive) flag, such as diff -r olddir newdir, which compares every file with a matching name in both directories, reporting differences file by file, as well as noting any files that exist in one directory but not the other.

What does it mean when diff reports a line starting with < or >?

In the default (non-unified) diff output format, a line starting with < represents content from the first file that is not in the second, and a line starting with > represents content from the second file that is not in the first. This older format is less commonly used today than unified diff format (-u), but it still appears in some tools and older documentation.

How do I generate a diff that can later be applied to another copy of the file with patch?

Generate the diff in unified format and redirect it to a file, such as diff -u original.conf modified.conf > changes.patch. That patch file can then be applied to another copy of the original file elsewhere with patch < changes.patch, reproducing the exact same change without needing to manually re-type or copy the modification.

Why does diff show no output at all sometimes?

diff prints nothing at all, and exits with a status code of 0, when the two files being compared are completely identical. This is actually useful in scripts: checking whether diff produced any output, or checking its exit code directly, is a standard way to programmatically detect whether two files have diverged at all.