🔄 Linux diff Command

Compare Files Line by Line - Examples by Claude

What is diff?

The diff command compares files line by line and displays the differences between them. It's an essential tool for programmers, system administrators, and anyone who needs to track changes between file versions. The name literally means "difference". diff is the foundation for version control systems like git, and its output format is used universally in patch files and code reviews.

Example 1Basic File Comparison

diff file1.txt file2.txt
Compare two files and show the differences. This is the most basic use of diff.
# file1.txt contains:
apple
banana
cherry

# file2.txt contains:
apple
blueberry
cherry
2c2 < banana --- > blueberry
Understanding the output:
- "2c2" means line 2 changed (c = change)
- "< banana" shows the line from file1
- "---" is a separator
- "> blueberry" shows the line from file2

Example 2Unified Format (Most Common)

diff -u file1.txt file2.txt
Use unified format (-u) which is easier to read and is the standard for patch files. This is what git uses by default.
--- file1.txt 2025-11-02 10:30:00.000000000 -0400 +++ file2.txt 2025-11-02 10:35:00.000000000 -0400 @@ -1,3 +1,3 @@ apple -banana +blueberry cherry
Pro Tip: Lines starting with - were removed, lines with + were added. Lines without +/- are context (unchanged).

Example 3Side-by-Side Comparison

diff -y file1.txt file2.txt
Display differences side by side using -y flag. Great for visual comparison of files.
apple apple banana | blueberry cherry cherry
Note: The | symbol indicates a difference between the files.

Example 4Brief Output (Just Report Differences)

diff -q file1.txt file2.txt
Use -q (quiet) to just report whether files differ, without showing the actual differences. Perfect for scripts.
Files file1.txt and file2.txt differ
Pro Tip: Use in scripts with exit codes: diff -q returns 0 if identical, 1 if different, 2 if error.

Example 5Ignore Case Differences

diff -i file1.txt file2.txt
Ignore case differences with -i flag. "Apple" and "apple" will be considered the same.

Example 6Ignore White Space

diff -w file1.txt file2.txt
Ignore all white space differences using -w. Useful for comparing code where formatting might differ.
Related options:
-b = Ignore changes in amount of white space
-B = Ignore blank lines
-w = Ignore all white space

Example 7Compare Directories

diff -r dir1/ dir2/
Recursively compare two directories using -r flag. Shows differences in all files within the directories.
Only in dir1/: oldfile.txt Only in dir2/: newfile.txt diff -r dir1/config.txt dir2/config.txt 2c2 < setting=old --- > setting=new

Example 8Show Context Lines

diff -c file1.txt file2.txt
Show context format with -c flag. Displays several lines of context around each change.
*** file1.txt 2025-11-02 10:30:00.000000000 -0400 --- file2.txt 2025-11-02 10:35:00.000000000 -0400 *************** *** 1,3 **** apple ! banana cherry --- 1,3 ---- apple ! blueberry cherry

Example 9Specify Context Lines in Unified Format

diff -U 5 file1.txt file2.txt
Show 5 lines of context (instead of default 3) around each change. Useful when you need more context to understand changes.

Example 10Create a Patch File

diff -u original.c modified.c > changes.patch
Create a patch file that can be applied to other copies of the original file. This is how software patches are distributed.
Apply the patch later: patch original.c < changes.patch

Example 11Compare With Standard Input

cat file1.txt | diff - file2.txt
Use - (dash) to compare standard input with a file. Useful for comparing command output with a file.
# Compare current running config with saved config
ps aux | diff - saved_processes.txt

# Compare current directory listing with expected
ls -la | diff - expected_files.txt

Example 12Ignore Lines Matching Pattern

diff -I '^#' file1.txt file2.txt
Ignore lines matching a regular expression using -I. This example ignores comment lines starting with #.
Common use cases:
- Ignore timestamps: -I '^# Generated on'
- Ignore version comments: -I '^# Version'
- Ignore blank lines: -B

Example 13Show Only if Files Differ

diff -q file1.txt file2.txt && echo "Files are identical" || echo "Files differ"
Use in shell scripts to take action based on whether files differ. diff -q returns exit code 0 if identical, 1 if different.
# Example script usage
if diff -q config.txt config.backup > /dev/null; then
    echo "Config unchanged"
else
    echo "Config was modified!"
    diff -u config.txt config.backup
fi

Example 14Color Output (with colordiff)

colordiff -u file1.txt file2.txt
Use colordiff for colored output (must be installed separately). Makes differences much easier to spot visually.
# Install colordiff
sudo apt install colordiff      # Ubuntu/Debian
sudo dnf install colordiff      # RHEL/Rocky

# Use as drop-in replacement for diff
colordiff -u file1.txt file2.txt
Pro Tip: Create an alias: alias diff='colordiff'

Example 15Compare Three Files

diff3 file1.txt file2.txt file3.txt
Use diff3 to compare three files at once. Useful for three-way merges in version control.
Note: diff3 is a separate command but part of the diffutils package.

Example 16Exclude Files from Directory Comparison

diff -r --exclude="*.log" dir1/ dir2/
Exclude specific files or patterns when comparing directories. Very useful for ignoring temporary or generated files.
# Exclude multiple patterns
diff -r --exclude="*.log" --exclude="*.tmp" --exclude=".git" dir1/ dir2/

# Exclude from file
diff -r --exclude-from=.diffignore dir1/ dir2/

Example 17Compare and Show Only Specific Changes

diff -u file1.txt file2.txt | grep '^[+-]' | grep -v '^[+-][+-][+-]'
Filter diff output to show only added/removed lines, not the metadata. Useful for quick scanning of actual changes.

Example 18Compare Binary Files

diff -q binary1.bin binary2.bin
Compare binary files. diff will just report if they differ without trying to show line-by-line differences.
Binary files binary1.bin and binary2.bin differ
For detailed binary comparison: Use cmp -l or hexdump instead

Example 19Generate Statistics

diff -u file1.txt file2.txt | diffstat
Pipe diff output to diffstat to get a summary of changes (requires diffstat to be installed).
file1.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)

Example 20Real-World: Compare Config Files

# Compare current config with backup
sudo diff -u /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup

# Compare running config with new config before applying
diff -u /etc/mysql/my.cnf /tmp/new_my.cnf

# Show differences ignoring comments and blank lines
diff -u -B -I '^#' /etc/ssh/sshd_config /etc/ssh/sshd_config.default
Common sysadmin task: comparing configuration files before making changes or after updates.

📚 Additional Information

Understanding diff Output Formats

Normal Format (default):

2c2          # Line 2 changed
< banana     # Old content (from file1)
---          # Separator
> blueberry  # New content (from file2)

# Other codes:
a = added
d = deleted
c = changed

# Examples:
5a6    # After line 5, add line 6
3d2    # Delete line 3 (was line 2)
2,4c2  # Lines 2-4 changed to line 2

Unified Format (-u):

--- file1.txt  # Original file
+++ file2.txt  # Modified file
@@ -1,3 +1,3 @@  # Line numbers (old start,count new start,count)
 apple         # Unchanged (context)
-banana        # Removed from file1
+blueberry     # Added to file2
 cherry        # Unchanged (context)

Context Format (-c):

*** file1.txt  # Original
--- file2.txt  # Modified
***************
*** 1,3 ****    # Lines 1-3 in original
  apple        # Unchanged
! banana       # Changed (! marks changed lines)
  cherry       # Unchanged
--- 1,3 ----   # Lines 1-3 in modified
  apple
! blueberry
  cherry

Common diff Options

Option Description
-u, --unified Unified format (most common)
-c, --context Context format
-y, --side-by-side Side-by-side comparison
-q, --brief Report only whether files differ
-r, --recursive Recursively compare directories
-i, --ignore-case Ignore case differences
-w, --ignore-all-space Ignore all white space
-b, --ignore-space-change Ignore changes in amount of white space
-B, --ignore-blank-lines Ignore blank lines
-I RE, --ignore-matching-lines=RE Ignore lines matching regex
--exclude=PAT Exclude files matching pattern
-N, --new-file Treat absent files as empty
-a, --text Treat all files as text

Exit Codes

0 - Files are identical
1 - Files are different
2 - Error occurred

Related Commands

Command Purpose
diff Compare files line by line
diff3 Compare three files
sdiff Side-by-side diff (merge interactively)
cmp Compare files byte by byte
comm Compare sorted files line by line
patch Apply diff output to files
colordiff Colorized diff output
vimdiff Visual diff in vim
git diff Git's diff implementation

Real-World Use Cases

System Administration:

# Compare config before and after changes
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup
# Make changes...
diff -u /etc/nginx/nginx.conf.backup /etc/nginx/nginx.conf

# Check what changed after system update
diff -r /etc /backup/etc-before-update | less

# Compare user lists
diff <(cat /etc/passwd | sort) <(ssh remote-host 'cat /etc/passwd | sort')

# Find differences in installed packages
diff <(dpkg -l | awk '{print $2}') <(ssh remote 'dpkg -l | awk "{print \$2}"')

Development:

# Create patch for code review
diff -u original.py modified.py > feature.patch

# Compare build outputs
diff -r build-old/ build-new/

# Check if code formatting changed
diff -w -B original.c formatted.c

# Compare API responses
curl -s https://api.example.com/v1 | diff - <(curl -s https://api.example.com/v2)

Backup Verification:

# Verify backup matches original
diff -qr /data /backup/data || echo "Backup differs!"

# Compare directory structures only (not content)
diff <(cd dir1 && find . -type f | sort) <(cd dir2 && find . -type f | sort)

# Check if backup is up to date
if diff -q important.db backup/important.db > /dev/null; then
    echo "Backup is current"
else
    echo "Backup needs updating"
    cp important.db backup/important.db
fi

Working with Patches

Creating Patches:

# Single file patch
diff -u original.txt modified.txt > changes.patch

# Directory patch
diff -urN original-dir/ modified-dir/ > changes.patch

# With better context
diff -U 10 original.c modified.c > changes.patch

Applying Patches:

# Apply patch
patch < changes.patch

# Apply to specific file
patch original.txt < changes.patch

# Dry run (test without applying)
patch --dry-run < changes.patch

# Reverse a patch
patch -R < changes.patch

Advanced Techniques

Process Substitution:

# Compare command outputs
diff <(ls dir1) <(ls dir2)

# Compare sorted files
diff <(sort file1) <(sort file2)

# Compare remote and local
diff local.txt <(ssh server cat remote.txt)

# Compare git branches
diff <(git show branch1:file.txt) <(git show branch2:file.txt)

Filtering diff Output:

# Show only added lines
diff -u file1 file2 | grep '^+'

# Show only removed lines
diff -u file1 file2 | grep '^-'

# Count changes
diff -u file1 file2 | grep '^[+-]' | wc -l

# Get just filenames that differ
diff -qr dir1 dir2 | grep differ | awk '{print $2}'

Ignoring Patterns:

# Create .diffignore file
*.log
*.tmp
.git/
node_modules/
__pycache__/

# Use it
diff -r --exclude-from=.diffignore dir1/ dir2/

# Or inline
diff -r --exclude='*.pyc' --exclude='.git' --exclude='node_modules' src1/ src2/

diff vs Other Tools

Tool Best For Comparison Type
diff Text files, creating patches Line by line
cmp Binary files, quick checks Byte by byte
comm Sorted text files Line by line (shows common/unique)
vimdiff Interactive editing Visual, side-by-side
git diff Version control changes Line by line with git context

Performance Tips

  • Large files: Use -q first to check if files differ before full comparison
  • Directories: Use --exclude to skip unnecessary files
  • Binary files: Use -q or cmp instead of full diff
  • Network files: Copy locally first for faster comparison

Common Gotchas

  • Line ending differences: Windows (CRLF) vs Unix (LF) can cause every line to show as different
  • Trailing whitespace: May cause differences even if content looks the same
  • Tab vs spaces: Can make files appear different when they're functionally identical
  • File encoding: UTF-8 vs ASCII vs other encodings can cause issues

Useful Aliases

# Add to ~/.bashrc or ~/.bash_aliases
alias diff='diff --color=auto'
alias diffs='diff -y --suppress-common-lines'
alias diffstat='diff -u | diffstat'

# Function for config diff
confdiff() {
    diff -u -B -I '^#' "$1" "$2"
}

Scripts Using diff

Backup Comparison Script:

#!/bin/bash
# Compare production with backup and alert if different

PROD_DIR="/var/www/html"
BACKUP_DIR="/backup/html"
ALERT_EMAIL="admin@example.com"

if ! diff -qr "$PROD_DIR" "$BACKUP_DIR" > /dev/null 2>&1; then
    diff -ur "$PROD_DIR" "$BACKUP_DIR" | mail -s "Backup Differs from Production" "$ALERT_EMAIL"
    echo "Alert sent: Backup differs from production"
else
    echo "Backup matches production"
fi

Config Change Detector:

#!/bin/bash
# Monitor config file for changes

CONFIG="/etc/nginx/nginx.conf"
SNAPSHOT="/var/cache/nginx.conf.snapshot"

if [ ! -f "$SNAPSHOT" ]; then
    cp "$CONFIG" "$SNAPSHOT"
    exit 0
fi

if ! diff -q "$CONFIG" "$SNAPSHOT" > /dev/null; then
    echo "CONFIG CHANGED:"
    diff -u "$SNAPSHOT" "$CONFIG"
    logger "nginx config was modified"
    cp "$CONFIG" "$SNAPSHOT"
fi
Pro Tip for Beginners: Start with diff -u (unified format) as it's the easiest to read and most commonly used. Once comfortable, explore other formats and options.
Pro Tip for Sysadmins: Always diff config files before and after making changes. Keep the diff output as documentation of what changed. Use -I to ignore timestamp comments that change automatically.

Fun Facts

  • diff was created in the early 1970s at Bell Labs for Unix
  • The algorithm used is called the "Hunt-McIlroy algorithm"
  • git's diff is based on the same principles but optimized for version control
  • The unified diff format (-u) was created in 1990 for patch compatibility
  • diff is so fundamental that nearly every version control system uses its output format