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.conf between servers, or production.env against staging.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 — Free

Frequently Asked Questions

What is diff mode in Linux?
In Linux, "diff mode" refers to running the diff command 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 -u for 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 -u for readable output and -q to 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 with patch original.txt < changes.patch. The -u flag is required for patch compatibility.