By Manny Fernandez

May 16, 2026

Understanding the Linux diff Command: A Practical Guide

If you have ever needed to know exactly what changed between two versions of a file, the diff command is your best friend. It is a small, fast, and reliable tool that ships with virtually every Linux distribution. The catch is that its output can look cryptic the first time you see it. This guide walks you through how to use diff and, just as importantly, how to read what it tells you.

What diff Actually Does

At its core, diff compares two files line by line and reports the changes needed to turn the first file into the second. It does not modify anything. It simply describes the differences. That description can then be used by humans for review or by other tools, such as patch, to apply the changes automatically.

The basic syntax could not be simpler:

diff file1.txt file2.txt

diff reads both files, finds the lines that differ, and prints a summary. If the files are identical, it prints nothing at all and exits quietly. That silence is a feature, not a bug. It means you can use diff in scripts to check whether two files match.

Reading the Default Output

Let’s say you have two files. The first, old.txt, contains:

apple
banana
cherry
date

The second, new.txt, contains:

apple
blueberry
cherry
date
elderberry

Running diff old.txt new.txt produces something like this:

2c2
< banana
---
> blueberry
4a5
> elderberry

This is the traditional, or “normal,” output format. It looks intimidating, but it follows a tidy logic once you know the rules.

Each block of changes starts with a line that tells you what kind of change happened and where. The letter in the middle is the key:

  • c means a line was changed
  • a means a line was added
  • d means a line was deleted

The numbers around the letter refer to line numbers. The number on the left points to old.txt, and the number on the right points to new.txt.

So 2c2 means line 2 in the old file was changed into line 2 in the new file. The lines starting with < come from the first file, and the lines starting with > come from the second file. The --- is just a divider between the old version and the new version. In our example, banana became blueberry.

The second block, 4a5, means that after line 4 in the old file, a new line was added, and it appears as line 5 in the new file. Since this is an addition, there is no < line, only a > line showing elderberry.

A quick way to remember the direction of the arrows: < points back toward the first file you listed, and > points forward toward the second file.

The Unified Format: Much Easier to Read

The normal format works, but most people find the unified format far more intuitive. You enable it with the -u flag:

diff -u old.txt new.txt

This produces output that looks like this:

--- old.txt	2026-05-16 10:00:00
+++ new.txt	2026-05-16 10:05:00
@@ -1,4 +1,5 @@
 apple
-banana
+blueberry
 cherry
 date
+elderberry

This is the format you see in code reviews, pull requests, and patch files everywhere. Here is how to read it.

The first two lines identify the files. The --- line is the original file and the +++ line is the updated file. Each is shown with a timestamp.

The line beginning with @@ is called the hunk header. It tells you which part of the files this block describes. @@ -1,4 +1,5 @@ means the block covers 4 lines starting at line 1 in the original file, and 5 lines starting at line 1 in the new file.

After the header come the actual lines, and the first character of each tells the whole story:

  • A space means the line is unchanged. It appears in both files and is shown only for context.
  • A minus sign means the line was removed from the original.
  • A plus sign means the line was added in the new version.

Reading our example, banana was removed, blueberry was added in its place, and elderberry was added at the end. The unchanged lines around them give you context so you can see where the changes sit. By default, diff shows three lines of context above and below each change, which makes the result much easier to follow than the bare normal format.

Comparing Whole Directories

diff is not limited to single files. Point it at two directories with the -r flag and it compares them recursively:

diff -r project_v1/ project_v2/

This walks through both folder trees and reports every file that differs, every file that exists in only one of the directories, and the line level changes inside files that appear in both. It is a fast way to audit what changed between two copies of a project.

Add -q if you only want the summary without the line by line detail:

diff -rq project_v1/ project_v2/

This prints just one line per file that differs, which is perfect when you only care about which files changed rather than how.

Handy Options Worth Knowing

A few flags make diff noticeably more pleasant in everyday use.

The -i flag ignores case, so Apple and apple are treated as the same. The -w flag ignores all whitespace differences, which is useful when indentation or trailing spaces have changed but the actual content has not. The -b flag is a gentler version that ignores changes in the amount of whitespace but still notices whitespace where there was none before.

The -y flag shows a side by side comparison, with the two files printed in parallel columns. It is wider and uses more screen space, but some people find it easier to scan:

diff -y old.txt new.txt

A marker appears between the columns: a | for changed lines, a < for lines only in the first file, and a > for lines only in the second.

Finally, the --color=always option adds color to the output on terminals that support it, which makes additions and deletions pop out immediately.

Using diff with patch

One of the most powerful uses of diff is creating patch files. When you save unified diff output to a file, you create a record of changes that can be applied to other copies of the original:

diff -u old.txt new.txt > changes.patch

Someone else with a copy of old.txt can then run:

patch old.txt < changes.patch

and their file will be transformed into new.txt. This is the foundation of how software changes were shared for decades before graphical tools became common, and it still underpins a great deal of modern development.

A Simple Mental Model

If you remember nothing else, remember this. diff answers one question: what would I have to do to turn the first file into the second? Removed lines are marked with < or -. Added lines are marked with > or +. Everything else is just context and coordinates telling you where the changes live.

Start with diff -u for almost everything. It is readable, it is the standard, and it is the format the rest of the toolchain expects. Once the unified format feels natural, the normal format and the side by side view become easy to pick up too.

The diff command rewards a small investment of attention. Spend ten minutes getting comfortable with its output and you gain a tool you will reach for constantly, whether you are reviewing code, tracking configuration changes, or simply figuring out why two files that should be identical are not.

Recent posts

  • If you've spent any time configuring user authentication on... Full Story

  • DNS is one of those technologies that quietly underpins... Full Story

  • BGP issues on FortiGate firewalls usually trace back to... Full Story

  • Every time your laptop talks to your router, a... Full Story

  • If you've spent any time configuring NAT on a... Full Story

  • If you have spent any time configuring firewall policies... Full Story

  • High availability on FortiGate is one of those features... Full Story

  • If you've configured SD-WAN on a FortiGate, you've almost... Full Story

  • FortiLink is the management protocol that turns a FortiSwitch... Full Story

  • FortiSwitches are pretty rock solid from Mean Time Between... Full Story

  • This is a quicky tip.  Have you ever gone... Full Story

  • DNS is one of those quiet pieces of internet... Full Story

  • This article is an updated version of the previous... Full Story

  • You will add ns2 as a secondary (slave) BIND9... Full Story

  • In the process of deploying my lab, I needed... Full Story

  • RFC 8805, used to be known as Self-Correcting IP... Full Story

  • Years back, I wrote an article about certificate pinning. ... Full Story

  • FortiGates have the ability to send alerts to Microsoft... Full Story

  • In this post, I am going to walk through... Full Story

  • Troubleshooting VoIP on a FortiGate can feel like trying... Full Story

  • Prior to FortiOS 7.0, there were three commands to... Full Story

  • In this post, I am going to go over... Full Story

  • What we are going to do:  We are going... Full Story

  • Choosing between FGCP (FortiGate Clustering Protocol) and FGSP (FortiGate... Full Story

  • Creating a VLAN on macOS (The "Pro" Move) A... Full Story

  • This blog post explores the logic behind how macOS... Full Story

  • Pretty Fly for a Wi-Fi Tell My Wi-Fi Love... Full Story

  • Part of my daily gig is creating BoMs (Bill-of-Materials)... Full Story

  • ICMP introduces several security risks, but careful filtering, rate... Full Story

  • The command diag debug application dhcps -1 enables full... Full Story

  • In the world of FortiOS, execute tac report is... Full Story

  • LLDP; What is it The Link Layer Discovery Protocol... Full Story

  • What it actually does When you run diagnose fdsm... Full Story

  • Monkey Bites are bite-sized, high-impact security insights designed for... Full Story

  • I have run macOS in macOS with Parallels but... Full Story

  • Don't be confused with my other FortiNAC posts where... Full Story

  • This is the third session in a multi-part article... Full Story

  • Today I was configuring key-based authentication on a FortiGate... Full Story

  • Netcat, often called the "Swiss Army knife" of networking,... Full Story

  • At its core, IEEE 802.1X is a network layer... Full Story

  • In case you did not see the previous FortiNAC... Full Story

  • This is our 5th session where we are going... Full Story

  • Now that we have Wireshark installed and somewhat configured,... Full Story

  • The Philosophy of Packet Analysis Troubleshooting isn't about looking... Full Story

  • 1. High-Level Overview The FortiGate Wireless Intrusion Detection System... Full Story

  • What MIMO Actually Does Multiple Input, Multiple Output (MIMO)... Full Story

  • A practitioner's tour of the diagnose, test, and fnsysctl... Full Story