25. shell命令--diff
功能说明
diff (different)是 Linux 和 Unix 系统上一个非常有用的命令行工具,用于比较两个文件的内容,或者比较文件的一个标准输入版本和另一个文件版本。它的输出可以告诉我们两个文件之间的不同之处,这对于代码审查、文档版本控制等任务非常有用。
diff 命令在最简单的情况下,比较给定的两个文件的不同。如果使用“-”代替“文件”参数,则要比较的内容将来自标准输入。diff命令是以逐行的方式,比较文本文件的异同处。如果该命令指定进行目录的比较,则将会比较该目录中具有相同文件名的文件,而不会对其子目录文件进行任何比较操作。
语法格式
diff [选项] 文件1 文件2
SYNOPSIS
diff [OPTION]... FILES
选项说明
- - 指定要显示多少行的文本。此参数必须与-c或-u参数一并使用。
- -a或--text diff预设只会逐行比较文本文件。
- -b或--ignore-space-change 不检查空格字符的不同。忽略空格数量的变化。
- -B或--ignore-blank-lines 不检查空白行。忽略空行的增加或减少。
- -c 显示全部内文,并标出不同之处。输出上下文差异格式。与 -u 类似,但提供了更多的上下文行。
- -C或--context 与执行"-c-"指令相同。
- -d或--minimal 使用不同的演算法,以较小的单位来做比较。
- -D或ifdef 此参数的输出格式可用于前置处理器巨集。
- -e或--ed 此参数的输出格式可用于ed的script文件。
- -f或-forward-ed 输出的格式类似ed的script文件,但按照原来文件的顺序来显示不同处。
- -H或--speed-large-files 比较大文件时,可加快速度。
- -I或--ignore-matching-lines 若两个文件在某几行有所不同,而这几行同时都包含了选项中指定的字符或字符串,则不显示这两个文件的差异。
- -i或--ignore-case 不检查大小写的不同。忽略大小写差异。
- -l或--paginate 将结果交由pr程序来分页。
- -n或--rcs 将比较结果以RCS的格式来显示。
- -N或--new-file 在比较目录时,若文件A仅出现在某个目录中,预设会显示:
- Only in目录:文件A若使用-N参数,则diff会将文件A与一个空白的文件比较。
- -p 若比较的文件为C语言的程序码文件时,显示差异所在的函数名称。
- -P或--unidirectional-new-file 与-N类似,但只有当第二个目录包含了一个第一个目录所没有的文件时,才会将这个文件与空白的文件做比较。
- -q或--brief 仅显示有无差异,不显示详细的信息。
- -r或--recursive 比较子目录中的文件。递归地比较目录。它会比较目录中的同名文件,并递归地处理子目录。
- -s或--report-identical-files 若没有发现任何差异,仍然显示信息。
- -S或--starting-file 在比较目录时,从指定的文件开始比较。
- -t或--expand-tabs 在输出时,将tab字符展开。
- -T或--initial-tab 在每行前面加上tab字符以便对齐。
- -u,-U或--unified= 以合并的方式来显示文件内容的不同。输出统一的差异格式(也称为“unified diff”或“patch”格式)。这是最常用的格式之一,因为它易于阅读且常用于版本控制系统(如 Git)。
- -v或--version 显示版本信息。
- -w或--ignore-all-space 忽略全部的空格字符。忽略所有的空格差异(包括空格数量和空行)。
- -W或--width 在使用-y参数时,指定栏宽。
- -x或--exclude 不比较选项中所指定的文件或目录。
- -X或--exclude-from 您可以将文件或目录类型存成文本文件,然后在=中指定此文本文件。
- -y或--side-by-side 以并列的方式显示文件的异同之处。
- --help 显示帮助。
- --color 或 --colour 在输出中使用颜色来标记差异。
- --left-column 在使用-y参数时,若两个文件某一行内容相同,则仅在左侧的栏位显示该行内容。
- --suppress-common-lines 在使用-y参数时,仅显示不同之处。
- --strip-trailing-cr 输入时删除尾随的回车符
实践操作
1. 环境准备
mkdir -p /test/diff
cd /test/diff
seq 12 >file1.txt
seq 13 |rev >file2.txt
mkdir -p dir1/{a..c}/{1,2}
mkdir -p dir2/{a..d}/{1..3}
ls
head -15 -v file*
ls -R dir* |wc -l
2. 仅判断两个文件是否不同
diff --brief file1.txt file2.txt
3. 以正常模式比较差异和并排格式输出
diff file1.txt file2.txt
10c10 #表示第10行不同
< 10 #表示第一个文件内容
---
> 01 #表示第二个文件内容
12c12,13 #表示12行后与第二个文件不同
< 12 #表示第一个文件内容
---
> 21 #表示第二个文件内容
> 31 #表示第二个文件内容
diff file1.txt file2.txt -y -W 50 #并排格式输出
seq 14 >file1.txt
diff file1.txt file2.txt
diff file1.txt file2.txt -y -W 60
说明:
"|"表示前后2个文件内容有不同
"<"表示后面文件比前面文件少了1行内容
">"表示后面文件比前面文件多了1行内容
4. 以上下文 (context) 模式比较差异
diff -c file1.txt file2.txt
5. 以联合 (unified) 模式比较差异和生成补丁
diff -u file1.txt file2.txt
#当你想将一个文件从版本A更新到版本B时,但不想直接覆盖原始文件
#你可以使用 diff 命令生成一个补丁文件,然后将这个补丁应用到原始文件上。
seq 5 >file1.txt #模拟版本A
seq 10 >file2.txt #模拟版本B
diff -u file1.txt file2.txt >patch.txt #生成一个将 file1.txt 更新到 file2.txt 的补丁
cat file1.txt
patch file1.txt <patch.txt #使用 patch 命令将这个补丁应用到 file1.txt 上
cat file1.txt
6. 递归地比较两个目录
diff -r dir1/ dir2/
rm -rf dir1/a
diff -r dir1/ dir2/
rm -rf dir2/b
diff -r dir1/ dir2/
命令示例:1. 环境准备
mkdir -p /test/diff
cd /test/diff
seq 12 >file1.txt
seq 13 |rev >file2.txt
mkdir -p dir1/{a..c}/{1,2}
mkdir -p dir2/{a..d}/{1..3}
ls
head -15 -v file*
ls -R dir* |wc -l
输出结果:
[root@MineGi ~]# mkdir -p /test/diff
[root@MineGi ~]# cd /test/diff
[root@MineGi /test/diff]# seq 12 >file1.txt
[root@MineGi /test/diff]# seq 13 |rev >file2.txt
[root@MineGi /test/diff]# mkdir -p dir1/{a..c}/{1,2}
[root@MineGi /test/diff]# mkdir -p dir2/{a..d}/{1..3}
[root@MineGi /test/diff]# ls
dir1 dir2 file1.txt file2.txt
[root@MineGi /test/diff]# head -15 -v file*
==> file1.txt <==
1
2
3
4
5
6
7
8
9
10
11
12
==> file2.txt <==
1
2
3
4
5
6
7
8
9
01
11
21
31
[root@MineGi /test/diff]# ls -R dir* |wc -l
78
[root@MineGi /test/diff]#
命令示例:2. 仅判断两个文件是否不同
diff --brief file1.txt file2.txt
输出结果:
[root@MineGi /test/diff]# diff --brief file1.txt file2.txt
文件 file1.txt 和 file2.txt 不同
[root@MineGi /test/diff]#
命令示例:3. 以正常模式比较差异和并排格式输出
diff file1.txt file2.txt
diff file1.txt file2.txt -y -W 50
seq 14 >file1.txt
diff file1.txt file2.txt
diff file1.txt file2.txt -y -W 60
输出结果:
[root@MineGi /test/diff]# diff file1.txt file2.txt
10c10
< 10
---
> 01
12c12,13
< 12
---
> 21
> 31
[root@MineGi /test/diff]# diff file1.txt file2.txt -y -W 50
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 | 01
11 11
12 | 21
> 31
[root@MineGi /test/diff]# seq 14 >file1.txt
[root@MineGi /test/diff]# diff file1.txt file2.txt
10c10
< 10
---
> 01
12,14c12,13
< 12
< 13
< 14
---
> 21
> 31
[root@MineGi /test/diff]# diff file1.txt file2.txt -y -W 60
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 | 01
11 11
12 | 21
13 | 31
14 <
[root@MineGi /test/diff]#
命令示例:4. 以上下文 (context) 模式比较差异
diff -c file1.txt file2.txt
输出结果:
[root@MineGi /test/diff]# diff -c file1.txt file2.txt
*** file1.txt 2024-12-03 15:08:20.305538645 +0800
--- file2.txt 2024-12-03 15:07:04.047679286 +0800
***************
*** 7,14 ****
7
8
9
! 10
11
! 12
! 13
! 14
--- 7,13 ----
7
8
9
! 01
11
! 21
! 31
[root@MineGi /test/diff]#
命令示例:5. 以联合 (unified) 模式比较差异和生成补丁
diff -u file1.txt file2.txt
seq 5 >file1.txt
seq 10 >file2.txt
diff -u file1.txt file2.txt >patch.txt
cat file1.txt
patch file1.txt <patch.txt
yum install -y -q patch
patch file1.txt <patch.txt
cat file1.txt
输出结果:
[root@MineGi /test/diff]# diff -u file1.txt file2.txt
--- file1.txt 2024-12-03 15:09:42.493107424 +0800
+++ file2.txt 2024-12-03 15:09:42.495107402 +0800
@@ -3,3 +3,8 @@
3
4
5
+6
+7
+8
+9
+10
[root@MineGi /test/diff]# seq 5 >file1.txt
[root@MineGi /test/diff]# seq 10 >file2.txt
[root@MineGi /test/diff]# diff -u file1.txt file2.txt >patch.txt
[root@MineGi /test/diff]# cat file1.txt
1
2
3
4
5
[root@MineGi /test/diff]# patch file1.txt <patch.txt
-bash: patch: 未找到命令
[root@MineGi /test/diff]# yum install -y -q patch
软件包 patch-2.7.1-12.el7_7.x86_64 已安装并且是最新版本
[root@MineGi /test/diff]# patch file1.txt <patch.txt
patching file file1.txt
[root@MineGi /test/diff]# cat file1.txt
1
2
3
4
5
6
7
8
9
10
[root@MineGi /test/diff]#
命令示例:6. 递归地比较两个目录
diff -r dir1/ dir2/
rm -rf dir1/a
diff -r dir1/ dir2/
rm -rf dir2/b
diff -r dir1/ dir2/
输出结果:
[root@MineGi /test/diff]# diff -r dir1/ dir2/
只在 dir2/a 存在:3
只在 dir2/b 存在:3
只在 dir2/c 存在:3
只在 dir2/ 存在:d
[root@MineGi /test/diff]# rm -rf dir1/a
[root@MineGi /test/diff]# diff -r dir1/ dir2/
只在 dir2/ 存在:a
只在 dir2/b 存在:3
只在 dir2/c 存在:3
只在 dir2/ 存在:d
[root@MineGi /test/diff]# rm -rf dir2/b
[root@MineGi /test/diff]# diff -r dir1/ dir2/
只在 dir2/ 存在:a
只在 dir1/ 存在:b
只在 dir2/c 存在:3
只在 dir2/ 存在:d
[root@MineGi /test/diff]#
输出说明
当你使用 diff 命令时,输出通常包括以下内容:
-
a<行号>,b<行号>:表示在文件 a 和 b 中有差异的行。例如,a3,5d 表示在文件 a 中删除了第 3 到 5 行。 <:表示在文件 a中有而文件b中没有的行。 >:表示在文件 b中有而文件a中没有的行。 c<行号>,<行号>c<行号>,<行号>:表示一个代码块(通常是多行)在两个文件中是不同的。