Linux 命令(119)—— diff 命令

  • 2020 年 2 月 20 日
  • 筆記

1.命令简介

diff(different)命令是以逐行的方式,比较文本文件的异同。

如果给定的文件名是 -,表示从标准输入读取内容。如果给定的文件是目录,则将会比较该目录中具有相同文件名的文件,默认情况下不会对其子目录文件进行任何比较操作。

由于历史原因,diff 有四种输出格式:

正常格式(选项 --normal )  并列格式(选项 -y, --side-by-side)  上下文格式(选项 -C NUM, -c, --context[=NUM])  合并格式(选项 -U NUM, -u, --unified[=NUM])

2.命令格式

diff [OPTION]... FILES

FILES 取值形式有如下几种:

FILE1 FILE2  DIR1 DIR2  DIR FILE  FILE DIR

FILES 除了上面的几种取值形式,也可以使用选项 –from-file(指定第一个文件)或 –to-file(指定第二个文件)。如果输入相同,退出状态为 0;如果输入不同,则为 1;如果出现故障,则为 2。

3.选项说明

注意,长选项的强制性参数对于短选项也是强制的。

-a, --text      所有的文件都视为文本文件来逐行比较  -B, --ignore-blank-lines      忽略插入删除空行引起的变化  -b, --ignore-space-change      忽略因空白符数量不同造成的差异  -C NUM  -c, --context[=NUM]      使用上下文格式输出,显示异行处上下指定数量的行(默认为 3 行)   --color[=WHEN]   	将输出着色;WHEN 可取值 never、always 或 auto(默认值)  -D, --ifdef=NAME  	输出与 "#ifdef NAME" 不同的合并文件  -d, --minimal      改变算法找出一组更小的变更。这会使 diff 变慢  -E, --ignore-tab-expansion  	忽略因 Tab 扩展引起的更改  -e, --ed      输出为一个有效的 ed 脚本  -F, --show-function-line=RE  	显示匹配 RE 的前面的行  --from-file=FILE1  	将 FILE 1 与所有文件进行比较;FILE 1 可以是一个目录  --GTYPE-group-format=GFMT  	用组格式 GFMT 格式化类型为 GTYPE 的输入组  --line-format=LFMT      用格式 LFMT 格式化所有输入行  --LTYPE-line-format=LFMT   	用行格式 LFMT 格式化类型为 LTYPE 的输入行  	上面三个选项和响应的格式提供了对输出的细粒度控制。  	行类型 LTYPE 可取值 old、new 或 unchanged,组类型 GTYPE 可取值 LTYPE 或 changed。  	组格式 GFMT 特含如下内容:  	%< FILE1 中的行  	%> FILE2 中的行  	%= FILE1 和 FILE2 中共有的行  	%[-][WIDTH][.[PREC]]{doxX}LETTER  		使用 printf 输出风格修饰 LETTER,LETTER 使用如下字母表示新组,下面的小写字母表示旧组  		F	首行行号          L	尾行行号          N	行数 = L-F+1          E	等于 F-1          M	等于 L+1          %(A=B?T:E)                if A equals B then T else E  	行格式 LFMT  特含如下内容:  	%L	行的内容  	%l	行的内容,不包括任何尾随的换行符  	%[-][WIDTH][.[PREC]]{doxX}n  		使用 printf 风格修饰输入行号 n  	组格式 GFMT 和行格式 LFMT 共有的内容:  	%%			表示百分号 %  	%c'C'		表示大写字母 C  	%c'OOO'	表示码值为八进制 000 的字符  	C			其他字符  --help  	显示帮助信息并退出  --horizon-lines=NUM  	保持共有前缀和后缀的 NUM 行  -I, --ignore-matching-lines=RE      忽略匹配正则表达式 RE 的行  -i, --ignore-case      忽略大小写  --ignore-file-name-case  	比较文件名时忽略大小写  -l, --paginate      将结果交由 pr 程序来分页  --label LABEL      输出比较结果时使用 LABEL 代替文件名和时间戳  --left-column  	只输出公共行的左列  -N, --new-file  	将缺席文件视为空文件。在比较目录时,若文件 A 仅出现在某个目录中,预设会显示:Only in 目录:文件 A。若使用 -N 参数,则 diff 会将文件 A 与一个空白的文件比较  -n, --rcs      将比较结果以 RCS 的格式来显示  --no-dereference  	不解析  --no-ignore-file-name-case  	比较文件名时大小写敏感  --normal  	使用正常格式输出比较结果。为默认输出格式  -p, --show-c-function  	显示每个更改在哪个 C 函数中  --palette=PALETTE  	当使用选项 --color 时,指定要使用的颜色。PALETTE 是使用冒号分隔的终端支持的能力列表  -q, --brief      仅报告文件是否相异,忽略差别的细节  -r, --recursive      当比较目录时,递归比较子目录  -S, --starting-file=FILE      当比较目录时,由 FILE 开始。这用于继续中断的比较  -s, --report-identical-files      当两个文件相同时报告  --speed-large-files  	使用启发规则加速操作那些有许多离散的小差异的大文件  --strip-trailing-cr  	去掉输入行尾的回车符 CR  --suppress-common-lines      在并列格式中不印出公共行  -T, --initial-tab      在每行前面加上 Tab 以便对齐  -t, --expand-tabs      在输出时将 Tab 扩展为空格  --tabsize=NUM  	一个 Tab 表示 NUM(默认 8) 个空格  --to-file=FILE2  	将所有文件与 FILE2 进行比较;FILE2 可以是一个目录  -U NUM  -u, --unified[=NUM]  	使用合并格式输出,输出 NUM(默认 3)行的统一上下文  --unidirectional-new-file  	将缺席的第一批文件视为空文件  -v, --version      输出版本信息并退出  -W, --width=NUM      使用 -y 选项采用列格式输出时,指定栏宽。缺省为 130  -w, --ignore-all-space      在比较行的时候忽略空白符  -y, --side-by-side      使用并格式输出两列   -Z, --ignore-trailing-space   	忽略行尾的空白符

4.常用示例

给定测试文件 file1 和 file2,其内容为十二生肖中动物的英文。 file1 内容:

mouse  cattle  tiger  rabbit  dragon  snake  horse  sheep  monkey  chicken  dog  pig

file2 内容:

mouse  cattle  tiger          rabbit  dragon  snake  h orse  sheeps  monkey  chicken

(1)比较两个文件的异同,使用正常格式输出。

diff file1 file2  4c4  < rabbit  ---  > 	rabbit  7,8c7,8  < horse  < sheep  ---  > h orse  > sheeps  11,12d10  < dog  < pig

diff 的正常输出格式有三种提示:

a - add  c - change  d - delete 

因此可以看出,上面的输出中 3c3 和 7,8c7,8 表示两者在 3、7 和 8 行内容有所不同;11,12d10 表示后者比前者少了 11 和 12 行。

特殊字符 < 表示该行属于第一个文件,> 表示该行属于第二个文件,— 为分隔符。

(2)比较两个文件的异同,使用并列格式输出,并指定列宽为 50。

diff -y -W50 file1 file2

其中特殊字符的含义如下:

| 表示前后 2 个文件内容有不同  < 表示后面文件比前面文件少了 1 行内容  > 表示后面文件比前面文件多了 1 行内容

(3)比较两个文件的异同,使用上下文格式输出,并只显示异行处上下各一行上下文。

diff -C1 file1 file2  *** file1	Sat Feb 15 22:24:46 2020  --- file2	Sat Feb 15 22:29:26 2020  ***************  *** 3,12 ****    tiger  ! rabbit    dragon    snake  ! horse  ! sheep    monkey    chicken  - dog  - pig  --- 3,10 ----    tiger  ! 	rabbit    dragon    snake  ! h orse  ! sheeps    monkey    chicken

这种方式在开头两行作了比较文件的说明,这里有三种特殊字符:

-	出现在前者,表示后者比前者少一行  +	出现在后者,表示后者比前者多一行  !	出现在两者,表示有差别的行

(4)比较两个文件的异同,使用合并格式输出,并只显示异行处上下各一行上下文。

diff -U1 file1 file2  --- file1	2020-02-15 22:24:46.522867000 +0800  +++ file2	2020-02-15 22:29:26.686867000 +0800  @@ -3,10 +3,8 @@   tiger  -rabbit  +	rabbit   dragon   snake  -horse  -sheep  +h orse  +sheeps   monkey   chicken  -dog  -pig

第一部分,也是文件的基本信息。— 表示第一个文件,+++ 表示第二个文件。 第二部分,@@包围的内容,其中 -3,10 表示输出的内容属于第一个文件的 3 至 10 行,+3,8 表示输出的内容属于第二个文件的 3 至 8 行。 第三部分,为比较后合并的内容。减号 – 表示后者比前者少了该行,加号表示后者比前者多了该行。

(5)比较时忽略空白字符(Tab、空格),使用正常格式输出。

diff -w file1 file2  8c8  < sheep  ---  > sheeps  11,12d10  < dog  < pig

可以发现,后者包含 Tab 的 rabbit 行和空格的 horse 行与前者比较时属于相同行。

(6)比较文件夹中同名文件的不同,使用正常格式输出。

ll dir1  total 4  -rw-r--r-- 1 root root  0 Feb 16 00:24 a.txt  -rw-r--r-- 1 root root 74 Feb 15 22:24 file    ll dir2  total 4  -rw-r--r-- 1 root root  0 Feb 16 00:24 b.txt  -rw-r--r-- 1 root root 69 Feb 15 22:29 file    diff dir1 dir2  Only in dir1: a.txt  Only in dir2: b.txt  diff dir1/file dir2/file  4c4  < rabbit  ---  > 	rabbit  7,8c7,8  < horse  < sheep  ---  > h orse  > sheeps  11,12d10  < dog  < pig

参考文献

[1] diff(1) manual [2] 每天一个Linux命令目录 [3] 每天一个Linux命令.diff 命令 [4] Linux 命令手册.diff 命令