diff 和 patch 命令(打补丁)

发布时间 2023-07-17 17:51:05作者: 小超不挑食

命令详解

diff 命令

diff 就是用在比对两个文件之间的差异的,并且是以行为单位来比对的!一般是用在 ASCII 纯文本文件的比对上。
由于是以行为比对的单位,因此 diff 通常是用在同一的文件(或软件)的新旧版本差异上!”

命令格式

diff [OPTION]  from-file  to-file > batch-file
  • from-file :一个文件名(或文件夹),作为原始比对文件的文件名;
  • to-file :一个文件名(或文件夹),作为目的比对文件的文件名;
  • batch-file :补丁(差异)文件,可选的。

注意,from-file 或 to-file 可以 - 取代,这个 - 代表“Standard input”之意

选项说明

-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:忽略行尾的空白符

patch命令

  • 作用:当diff比较新旧两个文件的差异后,将比较结果保存到patch文件里,然后使用patch命令利用补丁文件升级旧文件(打补丁),或把新文件回退成旧文件(卸载补丁):
命令格式
patch [OPTIONS] [ORIGFILE] < [PATCHFILE]]

[OPTIONS]:
--dry-run :模拟打补丁,不实际操作
-p N :指定要去掉的路径层数
-R :递归处理子目录中的文件
--verbose :显示详细的处理信息
--ignore-whitespace :忽略空格差异
--ignore-tab-expansion :忽略制表符扩展
--ignore-trailing-space :忽略行末空格的差异
--ignore-space-change :忽略空格的差异
--ignore-case :忽略大小写的差异
--forward :向前打补丁
--backward :向后打补丁
--strip N :去掉前缀 N 的路径名
--numeric-owner :使用数字来表示文件所有者和组
--exclude=file :从打补丁文件中排除文件
--fuzz=N :表示当某些行匹配多个修补程序时,可以放宽匹配的要求程度
--force :不检查补丁文件的正确性
--help :显示帮助信息
--version :显示版本信息

打补丁的一般流程

参考博客

  • diff命令:生成补丁包文件
    • 格式: diff –Nuar 旧版本文件 新版本文件 > 补丁包文件名.patch
  • patch命令:打补丁命令
    • 格式:patch –选项 <补丁包文件

例如
假设有version1.c(低版本)和version2.c(高版本)两个文件。

  1. 可以使用 diff 命令,生成补丁包:diff –Nuar version1.c version2.c > test.patch
  2. 利用 cat 查看补丁包文件内容会看到首行有旧版本、新版本文件目录,接着就是“-”或“<” 或“>” 或“+”跟着要修改的内容。
    • “<”/“-” :后面跟着要删除的内容。
    • “>”/“+” :后面跟着要增加的内容。
  3. 打补丁命令
    • 正向补丁 :patch –p0 < test.patch
    • 反向补丁(还原) :patch –Rp0 < test.patch
      (其中p代表剥离层级,0指略去patch文件0层目录,即从补丁包文件首行目录的根目录开始略去0层目录)