The diff command in Linux and Unix has been comparing files since 1974 — and it remains the foundation of every version control system, code review workflow, and deployment pipeline in use today. Yet most developers only know one format and two flags. This guide covers everything: what diff mode means, every output format with decision guidance, essential options ranked by real-world usage, and how to integrate bash diff into scripts and automation. Whether you call it linux diff, unix diff, or just plain diff — by the end you will know exactly which flags to reach for in every situation.
What Is diff and Why You Need It
diff is a command-line utility that compares two text files line by line and
outputs a minimal description of their differences. The name is short for "difference."
It was written by Douglas McIlroy and James Hunt and shipped with Unix Version 4 in 1974.
Today it is available on every Linux distribution, macOS, and BSD system — and its output
format is the basis for git diff, pull request views on GitHub, and patch
files distributed across the open-source ecosystem.
Understanding what is diff mode means understanding how diff represents changes. The command does not just flag "these files are different" — it produces a structured change set that tells you exactly which lines changed and how to transform file A into file B. That change set is the output of running diff, and its format is what developers mean when they talk about "diff mode" or "diff format."
Developers rely on linux diff for these everyday tasks:
- Code review: Reviewing a pull request is reviewing a diff. Every GitHub, GitLab, and Bitbucket PR view is built on unified diff output.
- Config management: Comparing
nginx.confbetween servers, orproduction.envagainststaging.env, catches configuration drift before it causes outages. - Patch distribution: Open-source contributions — including Linux kernel patches — have been shared as diff output files for 50 years.
- Deployment safety: Diffing a build artifact against the previous release confirms exactly what shipped. When something breaks, the diff narrows the search immediately. This is related to what static code analysis tools do at a higher level — both exist to surface problems before they reach production.
- Documentation tracking: Diffing Markdown files, READMEs, or man pages reveals what changed between software versions.
Quick Start: Your First diff in 60 Seconds
The simplest diff command in unix syntax takes two file paths as arguments:
diff file1.txt file2.txt
If the files are identical, diff exits with code 0 and prints
nothing. If they differ, it prints the differences and exits with code 1.
Exit code 2 means an error (file not found, permission denied, etc.).
A minimal example — create two files and compare them:
echo -e "apple\nbanana\ncherry" > fruits_v1.txt
echo -e "apple\nblueberry\ncherry" > fruits_v2.txt
diff fruits_v1.txt fruits_v2.txt Output:
2c2
< banana
---
> blueberry
That three-line output tells the whole story: line 2 was changed (c),
the left file had banana, the right file has blueberry. The next
section explains every symbol in detail.
Understanding diff Output Symbols
The cryptic-looking output of diff is actually a precise notation. Once you
know the diff symbols, you can read any diff output instantly.
Change Descriptors (Normal Format)
In the default (normal) diff format, each change block starts with a range line in the form:
L1[,L2]OP R1[,R2]
Where L is a line number in the left (first) file, R is a line
number in the right (second) file, and OP is one of three operations:
| Symbol | Meaning | Example range line | What it means |
|---|---|---|---|
a | Add | 3a4 | After line 3 of file1, add line 4 from file2 |
d | Delete | 5d4 | Delete line 5 from file1 (not in file2) |
c | Change | 2,3c2,4 | Replace lines 2-3 of file1 with lines 2-4 of file2 |
Below each range line are the actual content lines, prefixed with:
| Prefix | Meaning |
|---|---|
< | Line from the first (left) file |
> | Line from the second (right) file |
--- | Separator between the two sets of lines in a c block |
A complete annotated example:
3a4 # after line 3 of file1, add line 4 of file2
> orange # the added line
5d4 # delete line 5 of file1
< grape # the deleted line
7,8c7,9 # change lines 7-8 of file1 to lines 7-9 of file2
< fig # old line 7
< kiwi # old line 8
---
> fig # new line 7 (unchanged)
> kiwi leaf # new line 8 (modified)
> papaya # new line 9 (inserted) Unified Format Symbols (-u)
Unified format — the output of git diff and the modern standard — uses a different set of diff symbols:
| Prefix | Meaning |
|---|---|
--- | Header: the original (left) file |
+++ | Header: the modified (right) file |
@@ | Hunk header — line numbers and context size |
- | Line removed from the original file |
+ | Line added in the modified file |
| (space) | Context line — present in both files, unchanged |
The @@ hunk header looks like @@ -3,7 +3,8 @@, meaning:
-3,7— starting at line 3 of the original file, showing 7 lines+3,8— starting at line 3 of the new file, showing 8 lines
Three Ways to Format diff Output
Choosing the right diff file format is about matching the output to your audience and use case. Here are the four main formats with concrete guidance on when to use each one.
1. Normal Format (default)
How to invoke: diff file1.txt file2.txt (no flags needed)
Normal format is the original Unix diff output. It is compact and machine-readable but
hard to read without context. The change descriptors (a, d,
c) and line markers (<, >) were designed for
programs to parse, not humans to skim.
Best for: Simple scripts that parse diff output programmatically, or quick one-off comparisons where you just need to know "what changed."
Avoid when: You need to share the output with another person or create a patch file.
2. Unified Format (-u)
How to invoke: diff -u file1.txt file2.txt
Unified format is the modern standard. It merges both files into a single view, shows
3 lines of context above and below each change, and uses -/+
prefixes. This is exactly what git diff produces. It is more compact than
context format while being far more readable than normal format.
--- file1.txt 2026-03-31 10:00:00
+++ file2.txt 2026-03-31 10:05:00
@@ -1,5 +1,5 @@
apple
-banana
+blueberry
cherry
date
elderberry Best for: Patch files, code review, sharing diffs with teammates, any human-readable diff. This is the format to default to.
Control context lines with -U N (e.g. -U 0 for no context,
-U 10 for 10 lines): diff -U 5 file1.txt file2.txt
3. Context Format (-c)
How to invoke: diff -c file1.txt file2.txt
Context format is the predecessor to unified format. It shows both files separately with
! to mark changed lines. It uses more vertical space than unified but was
the patch standard before unified format became dominant.
*** file1.txt 2026-03-31 10:00:00
--- file2.txt 2026-03-31 10:05:00
***************
*** 1,5 ****
apple
! banana
cherry
date
elderberry
--- 1,5 ----
apple
! blueberry
cherry
date
elderberry Best for: Legacy systems and older patch tools that require context format. In new work, prefer unified format.
4. Side-by-Side Format (-y)
How to invoke: diff -y file1.txt file2.txt
Side-by-side format prints both files in two columns, aligned by line, with a separator column showing the relationship:
| Separator | Meaning |
|---|---|
| (space) | Lines are identical |
| | Lines differ |
< | Line only in left file (deleted) |
> | Line only in right file (added) |
apple apple
banana | blueberry
cherry cherry
Use --width=N to set the total output width (default 130):
diff -y --width=160 file1.txt file2.txt
Best for: Interactive terminal review of short files where you want both
versions visible simultaneously. Rarely covered by tutorials, but extremely useful for
config file comparisons. To suppress identical lines, add --suppress-common-lines.
Format Decision Matrix
| Situation | Best format | Flag |
|---|---|---|
| Creating a patch file | Unified | -u |
| Sharing with a teammate | Unified | -u |
| Parsing output in a script | Normal | (none) |
| Side-by-side terminal review | Side-by-side | -y |
| Legacy patch tool compatibility | Context | -c |
Essential diff Options (by Usage Frequency)
The diff man page lists dozens of options. Here are the ones you will actually use, sorted by how often they appear in real workflows.
Most Used
-u / --unified — Unified output format. The single most useful
flag. Use it by default for any diff you share or save.
-r / --recursive — Recursively compare directories, not just
individual files. Essential for linux diff files across whole project
trees.
diff -ru dir1/ dir2/ -i / --ignore-case — Treat uppercase and lowercase as equivalent.
Useful when comparing config files that may have inconsistent casing.
-w / --ignore-all-space — Ignore all whitespace differences.
Extremely useful when comparing code that was reformatted without semantic changes.
-b / --ignore-space-change — Ignore changes in the amount of
whitespace (but not all whitespace). More lenient than -w.
-q / --brief — Report only whether files differ, not how.
Perfect for scripts that only need a yes/no answer.
diff -q config_a.conf config_b.conf
# Outputs: "Files config_a.conf and config_b.conf differ" or nothing Moderately Used
-y — Side-by-side output. Add --suppress-common-lines to show
only differing lines.
-B / --ignore-blank-lines — Ignore changes that only add or
remove blank lines.
-E / --ignore-tab-expansion — Treat tabs and equivalent spaces
as identical.
-N / --new-file — When used with -r, treat absent
files as empty rather than skipping them. Ensures every file in both directories is
accounted for.
-x PATTERN — Exclude files matching a shell pattern during recursive
comparison:
diff -ru -x "*.log" -x ".git" dir1/ dir2/ --color[=WHEN] — Colorize output (GNU diff only, Linux). Values:
always, never, auto. Makes terminal output
much more readable:
diff --color=always -u file1.txt file2.txt Less Common but Powerful
--strip-trailing-cr — Strip carriage returns before comparing. Eliminates
the CRLF vs LF noise that plagues cross-platform projects.
-d / --minimal — Try harder to find a minimal diff. Slower
but produces cleaner output for highly similar files.
--speed-large-files — Use a heuristic that trades diff accuracy for speed
on very large files.
-l / --paginate — Pipe output through pr to
paginate it. Useful for long diffs in terminal sessions.
Real-World Examples
Compare Two Config Files
The most common use of linux diff 2 files:
diff -u nginx.conf.bak nginx.conf
If you only need to know whether they differ (not how), use -q:
diff -q nginx.conf.bak nginx.conf && echo "No changes" || echo "Files differ" Code Review: Generate a Patch
# Generate the patch
diff -u original.py modified.py > feature.patch
# Review it
cat feature.patch
# Apply it elsewhere
patch original.py < feature.patch This workflow is how early open-source projects distributed contributions — and still how the Linux kernel accepts patches from contributors who do not use GitHub.
Recursive Directory Comparison
Compare two versions of a project directory, excluding generated files:
diff -ru -x "node_modules" -x "*.log" -x ".git" project_v1/ project_v2/ To get just a summary of which files changed (without all the line diffs):
diff -rq project_v1/ project_v2/ Output will look like:
Files project_v1/config.yaml and project_v2/config.yaml differ
Only in project_v2/: new-feature.js
The diff -r approach works well on Linux and macOS. If you work primarily on Windows, Robocopy, PowerShell, and WinMerge offer native alternatives — our guide on how to tell which files are different in Windows folders covers every method.
Ignore Whitespace When Comparing Reformatted Code
diff -u -w original.js prettier-formatted.js
This is especially useful when a code formatter like Prettier has been applied to a file
— the -w flag suppresses all the whitespace noise and shows only
semantic changes. When you need a more capable visual tool for this kind of comparison,
the approach mirrors what VS Code's diff
viewer does with its "ignore whitespace" toggle.
Compare Two JSON Files
diff -u api_response_v1.json api_response_v2.json For structured JSON comparison where key order may differ, a dedicated tool works better. See the guide on comparing JSON objects online for options that normalize structure before diffing.
diff vs patch vs cmp
Three Unix tools handle file comparison tasks. Here is how they relate:
| Tool | What it does | Best for |
|---|---|---|
diff | Compares two text files and outputs the differences | Viewing changes, generating patches, scripting |
patch | Applies a diff output file to transform one file into another | Distributing and applying code changes |
cmp | Compares files byte by byte | Binary files, fast existence check, exact byte position of first difference |
Use diff when you need to understand what changed in text files.
Use patch when you have a diff file and want to apply it.
Use cmp when you need to compare binary files or get the byte offset of
the first difference.
# diff: what changed?
diff -u v1.txt v2.txt
# patch: apply the change
diff -u v1.txt v2.txt > changes.patch
patch v1.txt < changes.patch
# cmp: byte-level comparison (works on binaries too)
cmp image_v1.png image_v2.png diff3 is a related tool for three-way merges — it takes a base file and two
modified versions and merges them. This is what Git uses internally when resolving merge
conflicts. The concepts overlap with how developers use
string comparison at the code level — both are
fundamentally about finding and reconciling differences. In Java, this extends to choosing
the right equality method: see our guide on how to compare two strings in Java for the full range of options from .equals() to Collator-based locale-aware comparison.
Scripting with diff in Bash
The real power of bash diff emerges in automation. Because diff has predictable exit codes, it integrates naturally into shell scripts and CI pipelines.
Exit Code Checking
#!/bin/bash
diff -q config.prod.yaml config.staging.yaml
if [ $? -eq 0 ]; then
echo "Configs are in sync"
elif [ $? -eq 1 ]; then
echo "Configs differ — review before deploy"
exit 1
else
echo "Error running diff"
exit 2
fi Or more concisely using conditional execution:
diff -q file1.txt file2.txt >/dev/null 2>&1 \
&& echo "Identical" \
|| echo "Different" Capture Diff Output in a Variable
#!/bin/bash
DIFF_OUTPUT=$(diff -u original.conf updated.conf)
if [ -n "$DIFF_OUTPUT" ]; then
echo "Changes detected:"
echo "$DIFF_OUTPUT"
# Email it, log it, or open a ticket
fi Automated Config Drift Detection
A common DevOps pattern: snapshot a config file at deploy time and alert when it drifts.
#!/bin/bash
SNAPSHOT="/etc/nginx/nginx.conf.snapshot"
CURRENT="/etc/nginx/nginx.conf"
if [ ! -f "$SNAPSHOT" ]; then
cp "$CURRENT" "$SNAPSHOT"
echo "Snapshot created."
exit 0
fi
if ! diff -q "$SNAPSHOT" "$CURRENT" >/dev/null 2>&1; then
echo "CONFIG DRIFT DETECTED:"
diff -u "$SNAPSHOT" "$CURRENT"
fi Pre-commit Hook Example
#!/bin/bash
# .git/hooks/pre-commit
# Warn if package-lock.json changed without package.json changing
LOCK_CHANGED=$(git diff --cached --name-only | grep "package-lock.json")
PKG_CHANGED=$(git diff --cached --name-only | grep "^package.json$")
if [ -n "$LOCK_CHANGED" ] && [ -z "$PKG_CHANGED" ]; then
echo "Warning: package-lock.json changed without package.json"
echo "Run 'npm install' to reconcile."
exit 1
fi Count Changed Lines
diff -u file1.txt file2.txt \
| grep -E "^[+-]" \
| grep -v "^[+-]3" \
| wc -l This counts all added and removed lines — the same metric that GitHub shows in pull request statistics. It is a quick way to gauge the size of a change in a script.
Try Diff Checker Pro
Prefer a visual diff experience? Diff Checker Pro gives you split-view and unified-view comparisons with syntax highlighting for 20+ languages — no terminal required.
Add to Chrome — FreeFrequently Asked Questions
- What is diff mode in Linux?
-
In Linux, "diff mode" refers to running the
diffcommand to compare two text files line by line. It outputs a description of every addition, deletion, and change. The term also encompasses the specific output formats diff can produce — normal, unified (-u), context (-c), and side-by-side (-y) — each of which is sometimes called a "diff mode." - What do the symbols <, >, and --- mean in diff output?
-
In normal diff output,
<lines come from the first file,>lines come from the second file, and---is the separator in a change block. In unified format (-u),-marks lines removed from the original file and+marks lines added in the new file. - What is the difference between diff -u and diff -c?
-
Both show context lines. Unified (
-u) is compact — one combined view with-/+markers. Context (-c) is verbose — two separate views with!for changed lines. Unified is the modern standard used by git and GitHub. Use context format only for compatibility with legacy tools. - How do I compare two files with diff in Linux?
-
Run
diff file1.txt file2.txt. For readable output, add-ufor unified format. For side-by-side, add-y. If no output appears and the exit code is 0, the files are identical. - How do I recursively compare two directories with diff?
-
Use
diff -r dir1/ dir2/. Add-ufor readable output and-qto get a summary of which files differ without the line-level details. Exclude files with-x PATTERN. - How do I use diff output to create a patch file?
-
Run
diff -u original.txt modified.txt > changes.patch. Apply it withpatch original.txt < changes.patch. The-uflag is required forpatchcompatibility.