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.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-ris 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 (-U3or-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
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 file2to 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/ 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-Nit 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-xbut 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 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
-sis 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 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 needcolordiff.--strip-trailing-cr— CRLF normalization. BSD diff has no equivalent flag; preprocess withtr -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
- man7.org/linux/man-pages/man1/diff.1.html — Linux man pages (GNU diffutils), updated regularly.
- gnu.org/software/diffutils/manual/ — The official GNU diffutils Texinfo manual. More complete than the man page.
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 diffin 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
prfor 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
|| truealso 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: installcolordiffvia Homebrew and use it as a drop-in replacement. Addalias diff='diff --color=auto'(Linux) oralias 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