Linux diff Command: Compare Files and Find Changes
To compare two files on Linux, run diff followed by the old file and the new file:
diff settings.conf settings.conf.new
If the files are identical, diff prints nothing. If they differ, it shows the lines that changed. For output that is easier to read and share in a ticket, use unified format:
diff -u settings.conf settings.conf.new
That is the practical answer. The rest of this guide explains how to read the output without confusing āremoved from the first fileā with ādelete this immediately from production.ā
Why the diff command matters in IT support
Configuration problems often start with a vague report:
- āIt worked before the update.ā
- āThis server is configured exactly like the other one.ā
- āI only changed one line.ā
- āNobody touched the file.ā
diff replaces guessing with evidence. It can show whether two configuration files actually match, what changed between a backup and the current copy, or why one supposedly identical server behaves differently.
Common uses include:
- Comparing a working config with a broken one
- Reviewing a vendor-provided
.newor.distfile after an upgrade - Checking a current file against a backup
- Comparing exported command output from two servers
- Finding missing files or changed files in two directories
- Producing a patch-style record for a ticket or change request
The command only reads files unless you redirect its output somewhere. Running diff is safe. Acting on the result without understanding which file is which is where the ticket can get exciting.
Basic diff syntax
The basic form is:
diff [options] FILE1 FILE2
Think of FILE1 as the old or expected version and FILE2 as the new or observed version:
diff expected.conf current.conf
Suppose expected.conf contains:
port=8080
log_level=info
workers=4
And current.conf contains:
port=8080
log_level=debug
workers=4
Plain diff may print:
2c2
< log_level=info
---
> log_level=debug
This means line 2 in the first file changed to line 2 in the second file. The < line belongs to FILE1; the > line belongs to FILE2.
Plain output is compact, but unified output is usually friendlier.
Use diff -u for readable unified output
Run:
diff -u expected.conf current.conf
The output looks like this:
--- expected.conf
+++ current.conf
@@ -1,3 +1,3 @@
port=8080
-log_level=info
+log_level=debug
workers=4
Read it in order:
--- expected.confidentifies the first file.+++ current.confidentifies the second file.- Lines beginning with a space are unchanged context.
- A
-line exists in the first file but not the second. - A
+line exists in the second file but not the first.
The minus and plus signs describe the difference from file one to file two. They are not commands telling you what to remove or add.
Unified output is useful because it includes nearby unchanged lines. That context makes a single changed setting much easier to locate in a long config file.
Know what no output means
If this command prints nothing:
diff file-a.conf file-b.conf
The file contents are identical as far as diff is concerned.
You can also check the exit status:
diff file-a.conf file-b.conf
printf '%s\n' "$?"
diff commonly returns:
| Exit status | Meaning |
|---|---|
0 | No differences found |
1 | Differences found |
Greater than 1 | An error occurred |
This matters in scripts. Exit status 1 does not mean diff crashed; it means the comparison found a difference.
A safe shell check looks like:
if diff -q file-a.conf file-b.conf >/dev/null; then
echo "Files match"
else
status=$?
if [ "$status" -eq 1 ]; then
echo "Files differ"
else
echo "Comparison failed" >&2
fi
fi
Use diff -q when you only need yes or no
For a quick check, use brief mode:
diff -q server-a.txt server-b.txt
Example output:
Files server-a.txt and server-b.txt differ
This is useful during triage when you first need to establish whether there is a difference. If there is, rerun with -u to inspect it:
diff -u server-a.txt server-b.txt
Do not dump a 20,000-line unified diff into a ticket before checking whether a focused comparison would be more useful. Nobody enjoys scrolling past a certificate bundle to find one changed port number.
Ignore whitespace carefully
Whitespace can create noisy output, especially in generated files or files edited on different systems.
Useful options include:
diff -b file1 file2 # ignore changes in the amount of whitespace
diff -w file1 file2 # ignore all whitespace
diff -B file1 file2 # ignore changes where lines are all blank
You can combine them with unified output:
diff -u -b expected.conf current.conf
Be careful with -w. Whitespace can be meaningful in YAML, Python, Makefiles, and other formats. Ignoring it can hide the exact problem you are trying to find.
A good workflow is to run a normal unified diff first. If the output is mostly harmless spacing changes, try -b as a second view rather than treating whitespace as irrelevant by default.
Compare directories with diff -r
To compare two directory trees recursively, use:
diff -r /etc/app-working /etc/app-current
This reports changed files and files that exist on only one side.
For a quieter inventory first, combine recursive and brief modes:
diff -qr /etc/app-working /etc/app-current
Example:
Files /etc/app-working/app.conf and /etc/app-current/app.conf differ
Only in /etc/app-current: debug.conf
Then compare the specific changed file:
diff -u \
/etc/app-working/app.conf \
/etc/app-current/app.conf
This two-step approach is easier than throwing the entire directory tree onto the screen at once.
A beginner mistake is recursively comparing live system directories without narrowing the scope. The command remains read-only, but the output can become uselessly large. Start with the applicationās actual config directory, not all of /etc because you felt ambitious.
Compare command output from two systems
Sometimes the files you need do not exist yet. Capture the same diagnostic commands on both servers, then compare the results.
On server A:
{
hostname
uname -r
systemctl --failed
ss -lntp
} > server-a-diagnostics.txt
On server B:
{
hostname
uname -r
systemctl --failed
ss -lntp
} > server-b-diagnostics.txt
Copy both files to a safe working location and run:
diff -u server-a-diagnostics.txt server-b-diagnostics.txt
Some differences will be expected, such as the hostname. Others may expose a failed service, different kernel, or missing listener.
For cleaner comparisons, capture only the command that relates to the ticket. Focused evidence beats a giant diagnostic scrapbook.
A realistic config troubleshooting workflow
Imagine an application starts on web01 but fails on web02 after a change.
1. Back up the affected file
On the failing server:
sudo cp /etc/example/app.conf /etc/example/app.conf.before-fix
Use a timestamp when your teamās change process requires one.
2. Obtain the known-good file safely
Copy the working config to a temporary comparison path. Do not overwrite the failing config just to make the comparison easier.
For example:
scp admin@web01:/etc/example/app.conf /tmp/app.conf.web01
3. Compare the known-good file with the current file
sudo diff -u /tmp/app.conf.web01 /etc/example/app.conf
4. Separate expected differences from suspicious ones
Server names, IP addresses, and environment-specific paths may be intentionally different. A missing quote or changed port may not be.
5. Validate before applying anything
Use the applicationās config test if one exists. Examples include:
sudo nginx -t
sudo sshd -t
Do not copy these exact commands blindly for unrelated software. Check the application documentation or its manual page for the correct validation command.
6. Make the smallest justified change
Edit only the setting supported by the evidence, validate again, restart or reload only if required, and document the result.
The goal is not to make both files identical. The goal is to understand the difference causing the issue.
Save diff output for a ticket
Unified output can be saved as a patch file:
diff -u expected.conf current.conf > config-change.diff
Because diff returns status 1 when differences exist, automation with set -e may stop at that point even though the command worked. In an interactive shell, the redirection still creates the file normally.
Before attaching the output, inspect it:
less config-change.diff
Configuration files may contain passwords, tokens, internal hostnames, customer data, or private keys. Redact secrets through your approved process before pasting output into a ticket, chat, or public issue.
Common beginner mistakes
Reversing the file order
These commands describe the same difference from opposite directions:
diff -u old.conf new.conf
diff -u new.conf old.conf
The plus and minus lines swap. Label your files clearly and put the expected or older file first when possible.
Assuming every difference is a problem
A different hostname, node ID, IP address, or environment label may be correct. diff shows differences; it does not judge them.
Ignoring permissions errors
If diff says permission denied, do not copy protected files into a world-readable location as a shortcut. Use the minimum required privilege and a controlled working directory.
Comparing changing files
Logs, databases, caches, and active state files can change during the comparison. For logs, compare a defined time range or capture snapshots. Do not use plain text diff against a live database file.
Using diff for binary files
diff may only report that binary files differ. Use checksums to confirm exact equality or a format-specific tool to inspect meaningful changes. A package, image, or database needs different analysis than a text config.
Piping straight into an editor or patch tool
Review the output first. diff itself is read-only, but downstream commands can change files. Keep the inspection step separate while you are learning.
A helpdesk-ready comparison checklist
When a ticket points to a configuration difference:
- Confirm the exact file paths and affected hosts.
- Decide which file is expected and which is observed.
- Back up the current file before editing.
- Run
diff -qfor a quick match check. - Run
diff -ufor readable details. - Treat environment-specific differences as context, not automatic faults.
- Use the applicationās configuration validator.
- Make the smallest supported change.
- Verify service behavior after the change.
- Record the commands, relevant diff, validation, and outcome without leaking secrets.
That is a much stronger ticket note than āconfigs looked different, copied the good one over.ā
Practice comparing files safely
The syntax is easy. The useful skill is deciding which files to compare, reading the direction correctly, and separating expected differences from the one line breaking the service.
Practice Linux troubleshooting commands in Shell Samurai. It gives you a safe place to build command-line habits before you are comparing production configs while someone asks for an update every six minutes.
FAQ
How do I compare two files in Linux?
Run diff file1 file2. Use diff -u file1 file2 for readable unified output with surrounding context.
What does no output from diff mean?
No output normally means the files are identical. Exit status 0 confirms no differences; status 1 means differences were found.
What do plus and minus mean in diff output?
In unified output, - marks a line from the first file that is absent or changed in the second. + marks a line in the second file that is new or changed relative to the first.
How do I compare two directories in Linux?
Use diff -r directory1 directory2. Add -q for a brief inventory: diff -qr directory1 directory2.
How do I ignore whitespace with diff?
Use -b to ignore changes in the amount of whitespace, -w to ignore all whitespace, or -B to ignore blank-line-only changes. Do not ignore whitespace in formats where indentation matters.
Is diff safe to run on production files?
diff only reads its inputs and writes comparison output. It does not modify the files. Still, protect sensitive output and avoid feeding the result directly into commands that can change production files.
Practice This in a Real Terminal
Shell Samurai gives you safe Linux missions so the commands actually stick. Chapter 1 is free; the full practice path is a one-time purchase, not another subscription.