【linux-diff】详解
Linux diff
命令用于比较文件的差异。
diff以逐行的方式,比较文本文件的异同处。如果指定要比较目录,则diff会比较目录中相同文件名的文件,但不会比较其中子目录。
diff [-abBcdefHilnNpPqrstTuvwy][-<行数>][-C <行数>][-D <巨集名称>]
[-I <字符或字符串>][-S <文件>][-W <宽度>][-x <文件或目录>][-X <文件>]
[--help][--left-column][--suppress-common-line][文件或目录1]
[文件或目录2]
-<行数> 指定要显示多少行的文本。此参数必须与-c或-u参数一并使用。
-a或–text diff预设只会逐行比较文本文件。
-b或–ignore-space-change 不检查空格字符的不同。
-B或–ignore-blank-lines 不检查空白行。
-c 显示全部内文,并标出不同之处。
-C<行数>或–context<行数> 与执行"-c-<行数>"指令相同。
-d或–minimal 使用不同的演算法,以较小的单位来做比较。
-D<巨集名称>或ifdef<巨集名称> 此参数的输出格式可用于前置处理器巨集。
-e或–ed 此参数的输出格式可用于ed的script文件。
-f或-forward-ed 输出的格式类似ed的script文件,但按照原来文件的顺序来显示不同处。
-H或–speed-large-files 比较大文件时,可加快速度。
-l<字符或字符串>或–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=<列数> 以合并的方式来显示文件内容的不同。
-v或–version 显示版本信息。
-w或–ignore-all-space 忽略全部的空格字符。
-W<宽度>或–width<宽度> 在使用-y参数时,指定栏宽。
-x<文件名或目录>或–exclude<文件名或目录> 不比较选项中所指定的文件或目录。
-X<文件>或–exclude-from<文件> 您可以将文件或目录类型存成文本文件,然后在=<文件>中指定此文本文件。
-y或–side-by-side 以并列的方式显示文件的异同之处。
–help 显示帮助。
–left-column 在使用-y参数时,若两个文件某一行内容相同,则仅在左侧的栏位显示该行内容。
–suppress-common-lines 在使用-y参数时,仅显示不同之处。
实例1:比较两个文件
[[email protected] test3]# diff log2014.log log2013.log
3c3 # 第一个文件的第三行通过修改变成第二个文件的第三行就能跟第二个文件一样了
< 2014-03 # <代表第一个文件的内容
--- # 两个文件的分隔符
> 2013-03 # >代表第二个文件的内容
8c8
< 2013-07
---
> 2013-08
11,12d10
< 2013-11
< 2013-12
上面的"3c3"和"8c8"表示log2014.log和log20143log文件在3行和第8行内容有所不同;"11,12d10"表示第一个文件比第二个文件多了第11和12行。
请注意,diff的结果构成,就是由若干个块组成的,下面是一个块:
3c3 # 第一个文件的第三行通过修改变成第二个文件的第三行就能跟第二个文件一样了
< 2014-03 # <代表第一个文件的内容
--- # 两个文件的分隔符
> 2013-03 # >代表第二个文件的内容
我们可以看出,一个块的构成是这样的:
1、操作 # 3c3
2、不同:
先左文件
后右文件
举个栗子:
我们先来看一下text1的内容:
[[email protected] difftest]# cat text1
vth nb
bjfuvth
再来看一下text2的内容:
vth nb
bjfuvth
hh
我们来看一下diff的结果:
[[email protected] difftest]# diff text1 text2
2a3 # 第一个文件的第二行 a代表添加, 添加一行hh才能变成文件2
> hh
我们再来看一下并排输出(常用):
[[email protected] test3]# diff log2014.log log2013.log -y -W 50
2013-01 2013-01
2013-02 2013-02
2014-03 | 2013-03
2013-04 2013-04
2013-05 2013-05
2013-06 2013-06
2013-07 2013-07
2013-07 | 2013-08
2013-09 2013-09
2013-10 2013-10
2013-11 <
2013-12 <
[[email protected] test3]# diff log2013.log log2014.log -y -W 50
2013-01 2013-01
2013-02 2013-02
2013-03 | 2014-03
2013-04 2013-04
2013-05 2013-05
2013-06 2013-06
2013-07 2013-07
2013-08 | 2013-07
2013-09 2013-09
2013-10 2013-10
> 2013-11
> 2013-12
说明:
"|"表示前后2个文件内容有不同
"<"表示后面文件比前面文件少了1行内容
">"表示后面文件比前面文件多了1行内容
即 < 代表了左边文件独有的内容
>代表了右边文件独有的内容
| 代表了左边和右边不同
来参考一篇大神的博客
概述:
本文将要讨论的是diff命令,diff用来比较两个文件。当然文件比较的工具很多,windows系统下面就有不错的工具可以使用,例如常用的Beyond Compare,WinMerge都是图形界面的比较工具而且使用非常方便,如果你仅仅是在windows下工作,这些GUI的比较工具绝对是首选。对于在linux环境下工作的人来说,如果每次想看两个文件的区别都要将文件下载到windows环境然后用图形工具进行比较实在是太麻烦了。那么我们必须学会使用linux环境下的比较工具diff。
diff如何工作,如何理解diff的执行结果
diff分析两个文件,并输出两个文件的不同的行。diff的输出结果表明需要对一个文件做怎样的操作之后才能与第二个文件相匹配【或者这么理解:与第一个文件相比,第二个文件发生了那些变化】【git diff的结果输出也是如此】。diff并不会改变文件的内容,但是diff可以输出一个ed脚本来应用这些改变。
现在让我们来看一下diff是如何工作的,假设有两个文件:
//file1.txt
I need to buy apples.
I need to run the laundry.
I need to wash the dog.
I need to get the car detailed.
//file2.txt
I need to buy apples.
I need to do the laundry.
I need to wash the car.
I need to get the dog detailed.
我们使用diff比较他们的不同:
diff file1.txt file2.txt
输出如下结果:
2,4c2,4
< I need to run the laundry.
< I need to wash the dog.
< I need to get the car detailed.
---
> I need to do the laundry.
> I need to wash the car.
> I need to get the dog detailed.
我们来说明一下该输出结果的含义,要明白diff比较结果的含义,我们必须牢记一点,diff描述两个文件不同的方式是告诉我们怎么样改变第一个文件之后与第二个文件匹配。我们看看上面的比较结果中的第一行 2,4c2,4 前面的数字2,4表示第一个文件中的行,中间有一个字母c表示需要在第一个文件上做的操作(a=add,c=change,d=delete
),后面的数字2,4表示第二个文件中的行。
2,4c2,4 的含义是:第一个文件中的第[2,4]行(注意这是一个闭合区间,包括第2行和第4行)需要做出修改才能与第二个文件中的[2,4]行相匹配。
接下来的内容则告诉我们需要修改的地方,前面带 <
的部分表示左边
文件的第[2,4]行的内容,而带>
的部分表示右边
文件的第[2,4]行的内容,中间的 ---
则是两个文件内容的分隔符号
。
Normal模式
上面的部分我们说明了如何查看diff命令的结果,实际上对于上面的比较,我们使用的是diff命令的Normal
模式,这也是diff命令的默认模式
,也就是说diff两个文件的时候如果不加模式参数则是默认模式进行比较,其效果与(--normal
)一样,我们举一些例子来说明Normal
模式下的输出结果(前面已经说明了一种比较结果),为了直观查看两个文件的不同我在windows
下面通过BeyondCompare
工具列出两个文件的不同,而截图下面的黑色部分则是diff的比较输出截图。
第一个文件比第二个文件少了行的情况:
第一个文件比第二个文件多出行的情况:
第一个文件与第二个文件不相同的情况:
以上diff命令执行的时候没有指定额外的模式参数,所以其使用的是默认的Normal模式,效果与添加命令行参数--normal
是一样的。
Context模式
默认情况下的模式输出结果实际上是符合计算机的思维方式,不太直观,所以其输出结果并不能够很好的被人理解,diff命令除了默认
模式之外还提供了另外两种模式,Context
和Unified
模式,本节我们说说如何查阅Context
模式下的输出结果。diff
命令应用Context
模式只需要添加命令行参数 diff -c
即可,我们先看看两个案例文件:
接下来说明这两个文件以diff -c
方式比较的结果:
Unified模式
diff还有一种比较方式,也即Unified
模式,使用命令行 –u
来执行该模式的比较。其比较结果与Context
模式很像,但是简化了一些输出,我们看看我们的案例文件,与上面的一样:
使用diff –u
比较的结果:
可以看到其比较结果与Context
模式实际上差不多,只不过将比较结果合并到一起了。
比较目录
使用diff可以比较两个目录,其比较格式是 diff directory1 directory2
查看如下目录比较结果:
比较两个目录的时候无非是有的文件仅仅存在于某个目录中而在另一个目录中没有,如果存在同名的文件,则比较这两个文件的不同。diff比较目录的结果我们可以结合grep命令筛选出我们想要的输出,例如仅仅输出两个目录下不同的文件而忽略掉某一个目录独有另一个目录不存在的输出记录。
一些有用的参数:
diff还提供了一些有用的参数来控制比较行为与输出结果,一些常用的参数如下:-b --ignore-space-change
忽略空格,如果两行进行比较,多个连续的空格会被当作一个空格处理,同时会忽略掉行尾的空格差异。-w --ignore-all-space
忽略所有空格,忽略范围比-b更大,包括很多不可见的字符都会忽略。-B
忽略空白行。-y
输出两列,一个文件一列,有点类似GUI的输出外观了,这种方式输出更加直观。-W
大写W,当指定-y的时候设置列的宽度,默认是130-x, --exclude=PAT
比较目录的时候排除指定PAT模式的文件名的比较-i, --ignore-case
忽略两个文件中大小写的不同-e
将比较的结果保存成一个ed脚本,之后ed程序可以执行该脚本文件,从而将file1修改成与file2的内容相同,这一般在patch的时候有用。
diff -e 1.txt 2.txt > script.txt
这样就是生成了一个ed可以执行的脚本文件script.txt,生成脚本文件之后我们还需要做一个操作, 在脚本文件末尾添加ed的write指令,只需要执行 echo “w” >>script.txt 将w指令附加到脚本文件的最后一行即可。
那么如何应用该脚本文件呢,可以这样使用:
ed - 1.txt < script.txt
注意中间的 – 符号表示从标准输入中读取,而 < script.txt 则重定向script.txt的内容到标准输入。这样执行之后1.txt的内容将与2.txt完全相同。