使用 diff&patch 比较文件差异及打补丁

1,968 阅读5分钟

这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

diff命令是Linux系统中非常重要的工具,它用来比较两个文本文件的差异,特别是比较两个版本不同的文件以找到改动的地方,是svn、git等代码版本控制工具的不可或缺的一部分。

diff命令逐行比较两个文件的内容,并输出两个文件所不同的行,输出被称为补丁 (patch),然后可以使用patch命令打补丁,所谓打补丁,我理解的是修复两个文件的差异处,使二者的内容一致。

除此之外,diff命令还可以比较两个目录的内容,它会比较两个目录下相同文件名的文本文件。

diff比较两个文件/目录的差异

语法格式

diff [options] [文件1或目录1] [文件2或目录2]

常见选项参数如下:

参数描述
-<行数>指定要显示多少行的文本,此参数必须与-c或-u参数一并使用
-a或--text将所有文件当作文本文件来处理
-b或--ignore-space-change忽略空格字符的不同
-B或--ignore-blank-lines忽略空白行的不同
-c显示全部内容,并标出不同之处
-C<行数> 或--context<行数>比较指定行数的内容,也可以使用-c<行数>
-H或--speed-large-files比较大文件时,可加快速度
-l或--ignore-matching-lines若两个文件在某几行有所不同,而这几行同时都包含了选项中指定的字符或字符串,则不显示这两个文件的差异
-i或--ignore-case忽略大小写的不同
-l或--paginate结果交由pr程序来分页
-n或--rcs结果以RCS格式输出
-N或--new-file在比较目录时,若某文件仅出现在其中一个目录中,预设会显示:Only in目录:使用-N参数,则会将该文件与一个空白文件比较
-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=<列数>  以合并的方式来显示文件内容的不同
-w或--ignore-all-space忽略全部的空格字符
-W或--width在使用-y参数时,指定栏宽
-x或--exclude不比较选项中所指定的文件或目录
-y或--side-by-side以并列的方式显示文件的异同之处
--help显示帮助
--suppress-common-lines在使用-y参数时,仅显示不同之处

使用实例

比较两个文件:

vim log_2021_11_4.log

输入:

第1行
2021-11-04 LOG
我是2021年11月4日的日志
第4行
第5行
vim log_2021_11_5.log

输入:

第1行
2021-11-05 log
我是2021年11月5日的日志
第4行
第5行
第6行
diff log_2021_11_4.log log_2021_11_5.log
2,3c2,3
< 2021-11-04 LOG
< 我是2021年11月4日的日志
---
> 2021-11-05 log
> 我是2021年11月5日的日志
5a6
> 第6行

上面的"2,3c2,3"表示两个文件在2、3行内容有所不同,"5a6"表示第2个文件比第1个文件多了第6行。

说明:

  • a:add,添加的意思

  • c:change,修改的意思

  • d:delete,删除的意思

并排格式输出:

diff log_2021_11_4.log log_2021_11_5.log  -y -W 100

第1行                                           第1行
2021-11-04 LOG                                | 2021-11-05 log
我是2021年11月4日的日志                        | 我是2021年11月5日的日志
第4行                                           第4行
第5行                                           第5行
                                              > 第6行

说明:

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

上下文格式输出:

diff log_2021_11_4.log log_2021_11_5.log  -c
*** log_2021_11_4.log   2021-11-05 11:23:04.589000000 +0800
--- log_2021_11_5.log   2021-11-05 11:28:27.012000000 +0800
***************
*** 1,5 ****
  第1行
! 2021-11-04 LOG
! 我是2021年11月4日的日志
  第4行
  第5行
--- 1,6 ----
  第1行
! 2021-11-05 log
! 我是2021年11月5日的日志
  第4行
  第5行
+ 第6行

说明:

  • !:比较的文件两者有差别的行
  • :比较的文件的后者比前者多一行
  • :比较的文件的后者比前者少一行

比较两个目录:

ls diff_test1
# log  log_2021_11_4.log

ls diff_test2
# log  log_2021_11_5.log  log_2021_11_6.log

命令:

diff diff_test1 diff_test2

输出如下:

diff diff_test1/log diff_test2/log
1,2c1
< ./diff_test1/log
<
---
> ./diff_test2/log
Only in diff_test1: log_2021_11_4.log
Only in diff_test2: log_2021_11_5.log
Only in diff_test2: log_2021_11_6.log

patch通过补丁文件,来对文件打补丁

patch命令就是利用diff命令生成的补丁文件来实现源文件(夹)和目的文件(夹)的转换,使用它可以从源文件(夹)到目的文件(夹)进行转换,也可以从目的文件(夹)到源文件(夹)进行转换,目的是让源文件(夹)和目的文件(夹)内的内容变得一致。

patch命令使用也比较简单,这里不详细展开了。

比较两个文件并打补丁

diff -ruN  log_2021_11_4.log  log_2021_11_5.log > patch.log
patch log_2021_11_4.log patch.log 

执行完毕之后,文件log_2021_11_4.log内的内容会和文件log_2021_11_5.log一致,这是比较常用的一点。

原创不易,如果小伙伴们觉得有帮助,麻烦点个赞再走呗~

最后,感谢女朋友在工作和生活中的包容、理解与支持 !