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
- "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
-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
- 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