Linux diff 命令 | 逐行对比两个文件找出不同差异与结果分析
• 最后修改:2025-06-23 • 阅读量:4
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
。Ubuntu
,Debian
,Fedora
:他们所对应的内容行是上下文行,内容是相同的,以两个空格开头。- Arch Linux
:表示在对应的位置,第一个文件中有该内容,第二个文件没有;第二个文件也有该内容,但位置不同。+ Deepin
:表示第一个文件中的没有对应的内容。! CentOS
在第一个文件中和! Arch Linux
! CentOS
在第二个文件中,表示对应的更改内容。
默认情况下,上下文行数默认为3行。要指定另一个数字,使用-C ( --contexts ) 选项。
联合格式输出
联合格式输出是对上下文格式输出的整合,理解了上下文格式输出,就能理解联合格式输出,在这不做赘述。
忽略大小写
在上面的示例中你可能已经注意到 CentOS
与 Centos
作为了不同的内容对待,可以使用 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 系统中使用。