The diff man page is the authoritative reference for every flag, output format, exit code, and environment variable that the diff command understands — but most developers skim past it after learning two or three flags. This article is a structured companion to that man page: it maps every option to plain-language explanations, flags portability differences between GNU diffutils and BSD diff, and covers the under-served diff print workflow for paginating, colorizing, and saving output. If you want a tutorial with step-by-step examples, start with our complete diff command guide and come back here when you need the full reference.

man diff NAME diff — compare files line by line SYNOPSIS diff [OPTION]... FILES DESCRIPTION Full prose description of behavior, algorithm, and edge cases OPTIONS Every flag documented with type and default — the bulk of the page EXAMPLES Runnable shell snippets (not all platforms include this section) EXIT STATUS 0 = identical · 1 = different · 2 = error FILES Config paths, temp dirs, or spec references SEE ALSO cmp(1), diff3(1), patch(1), sdiff(1) core core detail core optional scripting ref ref
Standard sections of a Unix man page, shown in the order they appear in man diff.

What's the diff Man Page? Why Read It

A man page (short for "manual page") is the built-in documentation system inherited from Unix. Every standard Unix/Linux/macOS utility ships with one. The diff man page — accessed by running man diff — describes the exact behavior of the installed binary, including flags that never appear in tutorials.

There are actually several diff man pages depending on your platform:

  • GNU diffutils (Linux) — the most feature-rich version, maintained by the GNU Project. Source of truth: the GNU diffutils manual.
  • BSD diff (macOS, FreeBSD, OpenBSD) — historically more conservative, but macOS Ventura and later ship a diff that accepts most GNU long options.
  • POSIX diff — the minimum portable subset standardized in IEEE Std 1003.1 (Open Group). Anything not in POSIX may not work across platforms.

The man7.org diff page is the online mirror most Linux developers bookmark. BSD users should check the FreeBSD or OpenBSD project man pages, or simply run man diff locally.

Why read it instead of a tutorial? Tutorials teach the 80% case. The man page documents the edge flags — the ones you need when comparing binary files, handling CRLF line endings, feeding input from stdin, or generating output for automated patch pipelines. For the full picture of comparing files in Linux beyond just diff, see our dedicated overview.

Reading the SYNOPSIS: Syntax Breakdown

Every man page opens with a SYNOPSIS section. The diff SYNOPSIS looks like this:

diff [OPTION]... FILES

Conventions used throughout the man page:

  • [OPTION]... — zero or more options in any order. The ellipsis means repeatable.
  • FILES — exactly two file paths, or - for stdin. When both arguments are directories, diff compares them recursively (if -r is set) or lists which files differ.
  • Short flags start with a single dash: -u, -r, -i.
  • Long flags start with two dashes: --unified, --recursive, --ignore-case. Long flags are GNU extensions — they may not exist verbatim on BSD systems.
  • Flag arguments are joined with = for long flags (--unified=3) or appended directly / separated by space for short flags (-U3 or -U 3).

Options can be combined when they take no argument: -uri is equivalent to -u -r -i. Options that take arguments cannot be combined this way.

The Complete Flag Reference

The table below covers every significant flag from the diff man page across all three implementations. Portability columns: P = POSIX, G = GNU diffutils, B = BSD/macOS. ✓ = supported, — = not supported or not guaranteed.

Short Flag Long Form (GNU) Purpose POSIX GNU BSD/macOS
-u --unified[=N] Unified output format; N lines of context (default 3)
-c --context[=N] Context output format; N lines of context (default 3)
-y --side-by-side Side-by-side two-column output
-e --ed Output valid ed script to convert file1 into file2
-r --recursive Recursively compare subdirectories
-q --brief Report only whether files differ (no line content)
-s --report-identical-files Report when two files are identical
-i --ignore-case Ignore case differences in file content
-w --ignore-all-space Ignore all whitespace when comparing lines
-b --ignore-space-change Ignore changes in amount of whitespace
-B --ignore-blank-lines Ignore changes whose lines are all blank
-I --ignore-matching-lines=RE Ignore changes where all lines match regex RE
-E --ignore-tab-expansion Ignore changes due to tab expansion
-Z --ignore-trailing-space Ignore white space at line end
-N --new-file Treat absent files as empty when comparing directories
-x --exclude=PAT Exclude files matching shell pattern PAT
-X --exclude-from=FILE Exclude files matching patterns in FILE
-W --width=N Output at most N print columns in side-by-side mode
-l --paginate Pass output through pr to paginate
-t --expand-tabs Expand tabs to spaces in output for alignment
-T --initial-tab Prefix each line with a tab to align tabs properly
-a --text Treat all files as text, even binary
-p --show-c-function Show C function name in unified/context headers
-F --show-function-line=RE Show the most recent line matching RE in hunk headers
-n --rcs Output in RCS diff format (older VCS format)
-D --ifdef=NAME Output merged file with #ifdef NAME guards
--label=LABEL Use LABEL instead of file name in output headers ✓ (recent)
--color[=WHEN] Colorize output; WHEN is never/always/auto
--strip-trailing-cr Strip trailing carriage return from input lines (Windows CRLF)
--from-file=FILE Compare FILE to each operand (FILE is always "old")
--to-file=FILE Compare each operand to FILE (FILE is always "new")
--speed-large-files Use heuristic for large files with many small changes
--horizon-lines=N Keep at least N lines of common prefix/suffix context
--suppress-blank-empty Suppress space/tab before empty output lines
-v --version Output version information and exit

The table above covers the flags you are most likely to encounter in the diff man page. For the definitive list, run diff --help (GNU) or man diff on your target system. Flags not in POSIX should be avoided in scripts intended to run across platforms.

Output Format Options: Normal, Unified, Context, Side-by-Side

Which output format should I use? Need to compare files Will you use patch(1) later? YES Unified diff -u / --unified NO Visual scan side by side? YES Side-by-Side diff -y / --side-by-side NO Legacy system? YES Context diff -c / --context NO Normal diff (no flag)
Decision tree for picking the right diff output format based on your use case.

The diff man page defines four primary output formats. Understanding when to use each is as important as knowing the flags themselves.

Normal (default)

No flag required. Produces terse change commands in the form Rc, Ra, Rd where R is a line range and the letter means change, add, or delete. Lines from file1 are prefixed with <, lines from file2 with >.

$ diff a.txt b.txt
3c3
< foo
---
> bar

Best for: small files, human eyeballing, minimal noise. Not suitable for patch — unified format is the patch standard.

Unified (-u / --unified)

The format used by git diff and virtually all modern patch workflows. A hunk header looks like @@ -old_start,old_count +new_start,new_count @@. Lines prefixed - were removed; + were added; space is context.

$ diff -u a.txt b.txt
--- a.txt    2026-05-27 10:00:00.000000000 +0000
+++ b.txt    2026-05-27 10:01:00.000000000 +0000
@@ -1,5 +1,5 @@
 line1
 line2
-foo
+bar
 line4
 line5

Control context lines with -U N (e.g., -U0 for zero context, useful in tight diff pipelines). Unified format is required by patch.

Context (-c / --context)

Older than unified. Shows both files in separate blocks with ! for changed lines, + for added, - for removed. More verbose, rarely used in new workflows, but required by some legacy systems. POSIX mandates -c, -e, and -u as standardized output formats.

Side-by-Side (-y / --side-by-side)

Prints the two files in parallel columns. A pipe | marks changed lines, < marks lines only in file1, > only in file2. Pair with -W 200 (or your terminal width) to prevent wrapping.

$ diff -y --width=80 a.txt b.txt
line1                           line1
line2                           line2
foo                           | bar
line4                           line4

Use --suppress-common-lines (GNU only) to hide identical lines and focus on the diffs. Side-by-side is the closest the CLI gets to a visual diff tool — for a full browser-based side-by-side view, see the CTA at the end of this article.

Whitespace, Case & Blank-Line Handling

One of the most practical sections of the diff man page covers the flags that control how whitespace and casing are treated. These four flags solve the majority of "noisy diff" problems:

  • -w / --ignore-all-space — the strongest whitespace flag. Ignores every space and tab character when comparing lines. A line with leading indent is treated the same as one without. POSIX-portable.
  • -b / --ignore-space-change — weaker than -w. Treats runs of whitespace as equivalent but still distinguishes between a line with spaces and a line without any. POSIX-portable.
  • -i / --ignore-case — case-insensitive comparison. Useful for comparing markup or config files where casing drifts. POSIX-portable.
  • -B / --ignore-blank-lines — ignores change blocks where all lines in the block are blank. Separating logical sections with blank lines without triggering a diff is the common use case. GNU and BSD; not POSIX.

Less common but useful:

  • -E / --ignore-tab-expansion — considers tabs and equivalent spaces the same. Useful when comparing files from editors that disagree on tab width.
  • -Z / --ignore-trailing-space — ignores trailing whitespace only (not leading or internal). Pairs well with editors that strip trailing spaces inconsistently.
  • --strip-trailing-cr (GNU only) — strips the carriage return from lines before comparison. Essential when comparing files across Windows (CRLF) and Unix (LF) environments.
  • -I RE / --ignore-matching-lines=RE — ignores any change block where all lines match the extended regular expression RE. Classic use: diff -I '#.*' file1 file2 to ignore comment changes.

Combine flags: diff -wBi file1 file2 ignores whitespace, blank lines, and casing simultaneously. This is often the right starting point when comparing auto-generated or formatted files.

Directory Comparison Flags

diff -r dir-A/ dir-B/ dir-A/ dir-A/ config.yaml app.js lib/ utils.js legacy.js dir-B/ dir-B/ config.yaml app.js lib/ utils.js newfeature.js identical differs identical differs only in one side legacy.js only in A · newfeature.js only in B
diff -r dir-A/ dir-B/ walks both trees recursively and categorizes every file as identical, different, or unique to one side.

When both operands are directories, diff compares all files with matching names. The following flags control that behavior:

  • -r / --recursive — descend into subdirectories recursively. Without this flag, diff only looks at the top-level directory contents.
  • -q / --brief — suppress line-level output; report only which files differ. Combined with -r, this is the fastest way to audit two directory trees: diff -rq dir1/ dir2/
  • -s / --report-identical-files — explicitly report files that are identical (normally silently skipped). Useful for audits where you need to confirm all expected files are present and unchanged.
  • -N / --new-file — treat absent files as empty. Without this flag, diff prints "Only in dir1:" messages for files not present in the other directory instead of showing a full diff. With -N it treats the missing file as an empty file and shows all lines as added/deleted.
  • -x PAT / --exclude=PAT — skip files or directories matching shell glob PAT. Repeatable: diff -r -x '*.pyc' -x '__pycache__' src/ build/
  • -X FILE / --exclude-from=FILE — like -x but reads patterns from FILE (one per line). Handy for long exclude lists or sharing exclude patterns across scripts.
  • --from-file=FILE (GNU only) — compare FILE against every operand. Useful when diffing one base file against multiple variants without a shell loop.

A practical directory comparison that skips VCS metadata and byte-compiled files:

diff -rq \
  -x '.git' -x '.svn' \
  -x '*.pyc' -x '*.o' \
  project-v1/ project-v2/

For more on comparing directory trees on Windows, see our guide to finding different files in Windows folders, and for PowerShell equivalents, see the PowerShell diff guide.

Printing & Saving diff Output

diff | pr | less — paginated printing pipeline diff -u file1 file2 raw unified diff stdout → pipe | pr --header="Diff" adds headers & page breaks at 66 lines | less -R (ANSI colors) scrollable pager / to search, q to quit Replace less with lpr to send directly to the printer
The diff | pr | less pipeline turns raw diff output into paginated, header-labelled, scrollable output.

The diff print workflow is rarely documented but frequently needed when producing reports, sharing output over email, or creating a permanent audit record.

The built-in -l flag

The POSIX -l flag (--paginate in GNU) automatically pipes output through pr before printing. pr adds headers with the filename and date, and paginates the output into 66-line pages:

diff -ul file1.txt file2.txt | lpr

Or use pr directly for more control:

diff -u file1.txt file2.txt \
  | pr --header="Diff Report: file1 vs file2" \
  | lpr

Paginating in the terminal with less

For large diffs, pipe to less instead of scrolling the terminal:

diff -u file1.txt file2.txt | less

Add -R to make less interpret ANSI color codes from --color=always:

diff --color=always -u file1.txt file2.txt | less -R

Saving to a patch file

Redirect stdout to capture the diff for later use:

diff -u original.txt modified.txt > changes.patch

This is the standard way to create a patch for patch(1). The -u format is required; -c also works with most patch implementations.

Colored output

GNU diff (Linux) supports --color=auto or --color=always natively. On macOS (BSD diff), install colordiff via Homebrew:

# Linux (GNU diff)
diff --color=auto -u file1.txt file2.txt

# macOS (using colordiff)
brew install colordiff
colordiff -u file1.txt file2.txt

Add an alias in your ~/.zshrc or ~/.bashrc:

# GNU
alias diff='diff --color=auto'

# macOS — use colordiff as the diff replacement
alias diff='colordiff'

Saving to PDF

For a printable PDF of your diff print output, use enscript to convert plain text to PostScript and then ps2pdf for the final conversion:

# macOS
diff -u file1.txt file2.txt \
  | enscript -p - --header="diff report" \
  | ps2pdf - diff-report.pdf

# Linux (same tools, install via package manager)
sudo apt install enscript ghostscript
diff -u file1.txt file2.txt \
  | enscript -p - \
  | ps2pdf - diff-report.pdf

Alternatively, a2ps produces similar output and is available on both platforms. For HTML output (useful for pasting into documentation):

diff -u file1.txt file2.txt \
  | ansi2html > diff-report.html

ansi2html converts ANSI color codes to CSS-styled HTML spans — pair with --color=always for a colored HTML report.

Exit Status Codes Explained

The EXIT STATUS section of the diff man page is short but critical for scripting:

  • 0 — the two inputs are identical. No output is produced (unless -s is set).
  • 1 — differences were found. Output was written to stdout.
  • 2 — an error occurred (file not found, permission denied, invalid flag, binary file encountered without -a).

This three-code design is intentional and POSIX-standardized. Most programs use 0 for success and non-zero for failure; diff uses 1 to mean "different" (not an error) and 2 for genuine errors. Failing to account for exit code 1 in scripts is a common bug:

# WRONG: treats "files differ" as a script failure
set -e
diff file1 file2
echo "identical"

# CORRECT: explicitly handle all three cases
diff -q file1 file2 > /dev/null 2>&1
status=$?
if [ $status -eq 0 ]; then
  echo "identical"
elif [ $status -eq 1 ]; then
  echo "different"
else
  echo "error running diff" >&2
  exit 2
fi

When using set -e (exit on error) in bash scripts, diff exit code 1 will terminate your script unless you handle it explicitly. A common idiom: diff file1 file2 || true — but this swallows errors (code 2) too. The explicit check above is safer.

BSD vs GNU diff: Portability Matrix

diff Flag Portability Matrix Flag POSIX GNU/Linux BSD/macOS -u / --unified -y / --side-by-side -r / --recursive -N / --new-file --color[=WHEN] --suppress-blank-empty supported not available
Portability matrix for six key diff flags across POSIX, GNU/Linux, and BSD/macOS platforms.

The diff man page you read depends entirely on your platform. Linux ships with GNU diffutils; macOS and FreeBSD ship BSD diff. The two have converged significantly but key gaps remain.

Flags in GNU diff only

The following flags exist in GNU diffutils but are absent or unreliable on BSD diff:

  • --color[=WHEN] — native colorized output. BSD users need colordiff.
  • --strip-trailing-cr — CRLF normalization. BSD diff has no equivalent flag; preprocess with tr -d '\r'.
  • --from-file / --to-file — compare one file against multiple. Not available on BSD.
  • --speed-large-files — performance hint for large files.
  • --horizon-lines=N — controls the LCS alignment heuristic.
  • --suppress-blank-empty — cosmetic output cleanup.
  • -v / --version — BSD diff has no version flag; version is part of the OS release.

macOS diff (recent versions)

macOS Ventura (13+) ships a BSD diff that accepts many GNU long option names as aliases. The following GNU-style long flags now work on recent macOS: --unified, --context, --recursive, --brief, --ignore-case, --ignore-all-space, --label. Always verify with man diff on the actual target macOS version.

Reliable portable subset

For scripts that must run on Linux, macOS, and FreeBSD without modification, restrict yourself to POSIX flags only: -c, -e, -f, -r, -u, -w, -b plus the operands. Anything beyond this is an extension. See our diff command tutorial for practical examples using only the portable core.

Checking your diff version

# GNU/Linux — shows version number
diff --version

# macOS / BSD — no --version; check man page header
man diff | head -5

# Or check via package manager
brew info diffutils   # if GNU diffutils installed via Homebrew

You can install GNU diffutils on macOS via Homebrew (brew install diffutils), which places it at /opt/homebrew/bin/diff (Apple Silicon) or /usr/local/bin/diff (Intel). This gives you the full GNU flag set while keeping the system BSD diff intact.

How to Access the Man Page

Linux

man diff
# or via info for the full GNU manual:
info diff

The info command provides the complete GNU diffutils manual with cross-references — more detailed than the man page. Navigate with arrow keys, Enter to follow links, q to quit.

macOS

man diff

You get the BSD diff man page. If you have GNU diffutils installed via Homebrew:

man /opt/homebrew/share/man/man1/diff.1

FreeBSD and OpenBSD

man diff

FreeBSD and OpenBSD each maintain their own man pages. Check the project documentation sites for the exact version of your release.

Online man page mirrors

Searching the man page

Inside man diff, press / followed by a flag name to jump to it. Press n for the next match, N for previous. This works because man uses less as its pager by default. To search for a specific flag like --color:

man diff
# then type: /--color
# press n to find next match

Or use man -k diff to list all man pages whose descriptions mention "diff" — useful for discovering diff3, sdiff, cmp, and patch.

Frequently Asked Questions

How do I read the diff man page?
Run man diff in any terminal on Linux, macOS, or FreeBSD. Use j/k or arrow keys to scroll, / to search for a flag, and q to quit. On macOS you get the BSD man page; on Linux you get the GNU diffutils page. Online: man7.org (Linux) or the GNU diffutils manual.
What is the difference between GNU diff and BSD diff?
GNU diff (Linux) has more flags than BSD diff (macOS, FreeBSD). Key GNU-only flags: --color, --strip-trailing-cr, --from-file, --to-file, --speed-large-files. Recent macOS has gained many GNU long-option aliases, but subtle differences remain. Test on the target platform.
How do I print diff output?
Pipe through pr for paginated diff print: diff -u file1 file2 | pr | lpr. Save to a file with redirection: diff -u file1 file2 > changes.patch. For PDF: diff -u file1 file2 | enscript -p - | ps2pdf - diff.pdf.
What exit code does diff return?
0 = files identical, 1 = differences found, 2 = error. Always check all three in scripts — code 1 is not an error, and swallowing it with || true also hides genuine errors (code 2).
How do I get colored diff output in the terminal?
On Linux (GNU diff): diff --color=auto -u file1 file2. On macOS: install colordiff via Homebrew and use it as a drop-in replacement. Add alias diff='diff --color=auto' (Linux) or alias diff='colordiff' (macOS) to your shell profile.

Prefer a visual diff? Try our free browser extension Diff Checker Pro — side-by-side comparison with syntax highlighting, no copy-pasting into terminal required.

Install Diff Checker Pro — Free