Linux diff ( difference ) 命令用于逐行节比对两个文件,找出两个文件不同和差异。它还可以比较目录的内容,在比较目录内容时,diff 命令会比较目录中相同文件名的文件,但不会比较其中子目录。

diff 命令最常用于创建包含一个或多个文件之间差异的 patch,这个 patch 文件可以应用于 patch 命令。

diff 命令的定义解释

diff ( difference ) 命令用于逐行节比对两个文件,找出两个文件不同和差异,它还可以比较目录的内容。diff 命令最常用于创建包含一个或多个文件之间差异的 patch,这个 patch 文件可以应用于 patch 命令。diff 命令比较两个命令后会输出两个文件的不同之处。

diff 命令语法

diff  [选项]  源文件  目标文件

diff 命令的语法非常简单,参数比较多,但最重要的就是理解其输出格式

diff 命令使用示例及输出格式解释

示例及输出格式解释都是基于文件 file1.txt file2.txt,他们的内容分别为:

file1.txt 文件内容:
Ubuntu
Arch Linux
Debian
CentOS
Fedora
file2.txt 文件内容:
Deepin
Ubuntu
Debian
Arch Linux
Centos
Fedora

正常格式输出及示例

diff 命令运行的最简单的形式就是不带任何选项只带两个文本文件,这时会产生正常格式的输出:

diff file1.txt file2.txt

正常格式的输出会是如下形式:

0a1
> Deepin
2d2
< Arch Linux
4c4,5
< CentOS
---
> Arch Linux
> Centos

最重要的要记住在正常格式输出中以第一个文件(源文件)为参考标准,标记第二个文件(目标文件)所具有的差异。

输出格式解释

diff 命令正常格式输出中的内容由一个或多个描述差异的部分组成,每个部分看起来像这样:

变化命令
< 源文件行...
---
> 目标文件行...

每个 变化命令 包含如下内容,从左到右依次为:

  • 第一个文件(源文件)中的行号或行范围。
  • 一个特殊的 变化字符
  • 第二个文件(目标文件)中的行号或行范围。

变化字符 是以下字符之一:

  • a :添加行
  • c :变换行
  • d :删除行
开头符号解释
  • 开头的符号 < 表示删除该行内容
  • 开头的符号 > 表示添加该行内容

注意:如上表示变化的 ”添加“,”变换“,”删除“,都是对比第一个文件(源文件),第二个文件(目标文件)应该做的操作,以这种操作的形式,表现差异

示例中输出内容的解释

  • 0a1 :a 表示添加,在第一个文件(源文件)的第 0 行后面的位置,添加,第二个文件(目标文件)的第 1 行内容。
    • > Kubuntu> 表示添加,把该第二个文件中的行添加到第一个文件中。
  • 2d2 :d 表示删除,删除第一个文件中的第2行;d 符号后面的 2 表示:如果该行没有被删除,它将在第二个文件的第 2 行。
    • < Arch Linux< 表示删除,在第一个文件中删除了该行内容。
  • 4c4,5 :用第二个文件中的4-5行替换(变更)第一个文件中的第4行。
    • < CentOS< 表示删除,在第一个文件中,要被替换的行。
    • --- :分隔符,上面的要删除的,下面是要添加的
    • > Arch Linux> Centos> 表示添加,在第一个文件中要添加的行(内容来自第二个文件)。

上下文格式输出及示例

diff 命令使用上下文格式输出,需要使用 -c 选项:

diff -c file1 file2

输出内容为:

*** file1   2025-06-22 21:00:26.422426523 +0100
--- file2   2025-06-22 21:00:36.342231668 +0100
***************
*** 1,6 ****
  Ubuntu
- Arch Linux
  Debian
! CentOS
  Fedora

--- 1,7 ----
+ Deepin
  Ubuntu
  Debian
! Arch Linux
! Centos
  Fedora

输出格式解释

输出开始是用于比较的两个文件的名称和时间戳,后面是描述差异的一个或多个部分,每个部分看起来像这样:

***************
*** 第一个文件(源文件)的行号或行范围 ****
    第一个文件中的行...
--- 第二个文件(目标文件)的行号或行范围 ----
  第二个文件中的行...
  • 第一个文件(源文件)的行号或行范围:第一个文件(源文件)中行号,或者是以逗号分隔的行范围(开始行号 + 逗号 + 结束行号)
  • 第二个文件(目标文件)的行号或行范围:第二个文件(目标文件)中行号,或者是以逗号分隔的行范围(开始行号 + 逗号 + 结束行号)
  • 第一个文件中的行 :标记的不同的行和上下文行(即:内容相同行)。
  • 第二个文件中的行 :标记的不同的行和上下文行(即:内容相同行)。
标记行和上下文行解释
  • 以两个空格开头的行:它是上下文行,这些行的内容在两个文件中是相同的。
  • 以减号 - 开头的行:它只用来标记第一个文件中的内容,表示:第二个文件中不具有该行的内容,即:第二个文件中缺少该内容行。
  • 以加号 + 开头的行:它只用来标记第二个文件中的内容,表示:第一个文件中不具有该行的内容,即:第一个文件中缺少该内容行。
  • 以叹号 ! 开头的行:是两个文件之间相对应的内容不同的行。每组行以 ! 标记的两个文件的内容行是相对应的内容,标记在 第一个文件中的行 中表示在第一个文件中该位置是标记的内容,标记在 第二个文件中的行 中表示在第二个文件中该位置是标记的内容。

示例中输出内容的解释

在本例中,只有一个部分描述差异。

  • *** 1,6 **** :第一个文件中的内容行范围,起始行号 1,结束行号 6
  • --- 1,7 ---- :第二个文件中的内容行范围,起始行号 1,结束行号 7
  • UbuntuDebianFedora :他们所对应的内容行是上下文行,内容是相同的,以两个空格开头。
  • - Arch Linux :表示在对应的位置,第一个文件中有该内容,第二个文件没有;第二个文件也有该内容,但位置不同。
  • + Deepin :表示第一个文件中的没有对应的内容。
  • ! CentOS 在第一个文件中和 ! Arch Linux ! CentOS 在第二个文件中,表示对应的更改内容。

默认情况下,上下文行数默认为3行。要指定另一个数字,使用-C ( --contexts ) 选项。

联合格式输出

联合格式输出是对上下文格式输出的整合,理解了上下文格式输出,就能理解联合格式输出,在这不做赘述。

忽略大小写

在上面的示例中你可能已经注意到 CentOSCentos 作为了不同的内容对待,可以使用 i 选项忽略大小写的不同:

diff -ui file1.txt file2.txt

输出内容:

--- file1   2025-06-22 21:00:26.422426523 +0100
+++ file2   2025-06-22 21:00:36.342231668 +0100
@@ -1,6 +1,7 @@
+Deepin
 Ubuntu
-Arch Linux
 Debian
+Arch Linux
 CentOS
 Fedora

diff 命令选项解释

如下给出了 Linux diff 命令中所有选项的解释说明:

选项 解释说明
--normal 输出正常格式的对比内容(默认设置)
-q, --brief 当文件不同是,报告信息
-s, --report-identical-files 当文件相同时,报告文件相同
-c, -C NUM, --context[=NUM] 在上下文格式中输出指定的行数(默认为 3 行)
-u, -U NUM, --unified[=NUM] 在联合格式中输出指定的行数
-e, --ed 输出一个 ed 脚本
-n, --rcs 输出 RCS 格式的 diff 信息
-y, --side-by-side 输出一个两列的信息
-W, --width=NUM 每行最多输出的字符数(默认 130
--left-column 只输出公共行(相同行)的左列
--suppress-common-lines 不输出公共行(相同行)
-p, --show-c-function 显示每个更改在哪个C函数中
-F, --show-function-line=RE 显示最近匹配正则的行
--label LABEL 使用LABEL代替文件名和时间戳(可以重复)
-t, --expand-tabs 在输出中将制表符替换为空格
-T, --initial-tab 通过添加制表符使子符对齐
--tabsize=NUM 制表符占用 NUM 个打印列(默认为 8)
--suppress-blank-empty 在空行前禁止添加空格或制表符
-l, --paginate 通过‘pr’传递输出以对其进行分页
-r, --recursive 递归地比较找到的所有子目录
--no-dereference 不比较符号链接
-N, --new-file 将缺少的文件视为空文件
--unidirectional-new-file 将缺少的第一个文件视为空文件
--ignore-file-name-case 对比时忽略大小写
--no-ignore-file-name-case 比较文件名时要考虑大小写
-x, --exclude=PAT 排除与PAT匹配的文件
-X, --exclude-from=FILE 排除与 FILE 模式相匹配的文件
-S, --starting-file=FILE 比较目录时从 FILE 开始
--from-file=FILE1 FILE1 和所有运算对象比较;FILE1 可以是一个目录
--to-file=FILE2 把所有运算对象和 FILE2 比较;FILE2 可以是一个目录
-i, --ignore-case 比较时,忽略文件内容的大小写
-E, --ignore-tab-expansion 忽略 Tab 所引起的文件不同
-Z, --ignore-trailing-space 忽略行尾的空格
-b, --ignore-space-change 忽略空格所引起的变化
-w, --ignore-all-space 忽略所有空格
-B, --ignore-blank-lines 忽略连续的空行
-I, --ignore-matching-lines=RE 忽略所有匹配正则的行的变化
-a, --text 把所有文件作为文本文件对比
--strip-trailing-cr 输入时,移除行尾的回车
-D, --ifdef=NAME 输出信息与 #ifdef NAME 合并到一个文件
--GTYPE-group-format=GFMT 使用 GFMT 格式化 GTYPE 输入组
--line-format=LFMT 使用 LFMT 格式化所有输入行
--LTYPE-line-format=LFMT 使用 LFMT 格式化所有 LTYPE 输入行,这些格式选项提供了对输出的细粒度控制,笼统地输出使用选项 -D/--ifdef
-d, --minimal 努力寻找一组较小的更改
--horizon-lines=NUM 保留公共前缀和后缀的 NUM
--speed-large-files 假设大文件和许多分散的小更改
--color[=WHEN] 颜色的输出信息,WHEN 可取的值有 “never”、“always” 或 “auto”;不带值选项 --color 等同于 --color='auto'
--palette=PALETTE 当使用 --color 选项时,可用的颜色;PALETTE 是一个以冒号分隔的 terminfo 功能列表
--help 显示帮助信息并退出
-v, --version 显示版本信息并退出

LTYPE 和 GTYPE 解释说明

LTYPE 是 'old', 'new', 或 'unchanged'。

GTYPE 是 LTYPE 或 'changed'。

GFMT 和 LFMT 解释说明

仅 GFMT 可以包含的符号:

符号 解释说明
%< 来自 FILE1 的行
%> 来自 FILE2 的行
%= FILE1和FILE2 相同的行
%[-][WIDTH][.[PREC]]{doxX}LETTER LETTER 的印刷样式规范
F 第一行的行号
L 最后一行的行号
N 行数 = L-F+1
E F-1
M L+1
%(A=B?T:E) 如果 A = B,则 T = E

仅 LFMT 可以包含的符号:

符号 解释说明
%L 行内容
%l 排除尾部有换行符的行内容
%[-][WIDTH][.[PREC]]{doxX}n 输入行号的打印样式规范

GFMT 和 LFMT 都可以包含的符号:

符号 解释说明
%% %( % 需要使用 % 本身转义)
%c'C' 单个字符 C
%c'\OOO' 八进制编码为 OOO 的字符
C 字符 C(其他字符代表它们自己)

结语

在本教程中我们介绍了如何使用 diff ( difference ) 命令用于逐行节比对两个文件,找出两个文件不同和差异。它还可以比较目录的内容,在比较目录内容时,diff 命令会比较目录中相同文件名的文件,但不会比较其中子目录。diff 命令比较两个命令后会输出两个文件的不同之处。diff 命令最常用于创建包含一个或多个文件之间差异的 patch,这个 patch 文件可以应用于 patch 命令。

该 diff 命令可以在 Linux 系统中使用,也可以在 FreeBSD 系统中使用。