Patch,又称补丁程序,是1985年由
美国程序设计师
拉里·沃尔(Larry Wall)开发的Unix应用程序。它利用一个名为patch file(有时直接被称为patch)的
文本文件,更新文本文件。patch文件是一个包含差异列表的文本文件,由运行与原始和已修改文件相关的diff程序时产生。通过patch程序更新文件,通常被称为应用补丁或简单地修改文件。
命令应用
用途
对文件应用更改。
语法
patch [ -b [ -B Prefix ] ] [ -f ] [ -l ] [ -N ] [ -R ] [ -s ] [ -v ] [ -c | -e | -n ] [ -d Directory ] [ -D Define ] [ -F Number ] [ -i PatchFile ] [ -o OutFile ] [ -p Number ] [ -r RejectFile ] [ -x Number ] [ File ]
描述
patch 命令读取如何更改文件的源文件指示信息,然后应用这些更改。源文件包含由 diff 命令产生的差别列表(或者 diff 列表)。差异列表是比较两个文件和构建关于如何纠正差别的指示信息的结果。缺省情况下,patch 命令使用从标准输入读入的源文件,但是使用 -i 标志和 PatchFile 变量可以覆盖此设置。
差异列表有三种格式:正常、上下文或者是 ed 编辑器风格。patch 命令确定差异列表格式,除非被 -c、-e 或 -n 标志否决。
缺省情况下,文件的打过补丁的版本替换原始版本。指定 -b 标志时,每个补丁文件的原文件保存在同名的文件中,只是在文件名后附加了后缀 .orig。使用 -o 标志也可以指定输出的目的地。
-p 标志使得无需手工编辑补丁文件就可以定制补丁文件到本地用户目录结构中。通过指定从路径全称除去多少部分可以做到这一点。例如,如果补丁文件包含路径名称 /curds/
乳清/src/blurfl/blurfl.c,那么:
* -p 0 导致使用完整路径名。
* -p 1 除去前导斜杠,留下 curds/whey/src/blurfl/blurfl.c。
* -p 4 除去前导斜杠和前三个目录,留下 blurfl/blurfl.c。
不指定 -p 标志使得 patch 命令使用基本名称。在上面的示例中,此文件为 blurfl.c。
补丁文件格式
补丁文件必须包含单行或多行头信息,后跟单个或多个补丁。每个补丁必须包含一行或多行文件名标识,其格式由 diff -c 命令和单个或多个 diff 命令输出集产生,通常称为 hunks。
patch 命令跳过补丁文件中的任何前导文本,然后应用实际的差异列表,并且跳过任何后续文本。因而,可以将包含差异列表的文件或消息当成补丁文件使用,此时 patch 命令仍然有效。在这种情况下,如果整个差异列表使用一致的数量缩进,patch 命令也会调整其间距。
要更改原始文件中的行范围,每一补丁中的块(hunk)必须为单独的差异列表。补丁内连续块(hunk)的行号必须以升序方式出现。
文件名
如果没有指定
File 参数,要获得供编辑的文件名,patch 命令会执行下面的步骤:
1. 在上下文差异列表的头部分,文件名由以 ***(三个星号)或者 ---(三个破折号)开头的行确定。以 *** 开头的行表示获取补丁的文件,然而以 --- 开头的行表示应该应用补丁的文件名。选择存在文件的最短名称。
2. 如果在前导文本中有 Index:行,patch 命令尝试使用来自于那一行中的文件名。
3. 上下文差异文件头优先于 Index: 行。
4. 如果从前导文本中不能确定文件名,patch 命令提示输入需要打补丁的文件名。
5. 如果不能找到原始文件,但是有适合的 SCCS 或 RCS 文件可用,patch 命令尝试获取或检出文件。
6. 如果前导文本包含 Prereq: 行,patch 命令从先决条件行中获取第一个词(通常是版本号)并且检查输入文件看是否能找到那个词。如果找不到,patch 命令在继续运行前会提示确认。
应用程序
如果补丁文件包含不止一个补丁,patch 命令尝试应用每个差异列表,就好像它来自于单独的补丁文件。在这种情况下,为每个差异列表确定需要打补丁的文件名,并且审查每个差异列表前的头文本以获得如文件名和修订版级别的信息。
如果指定 -c、 -e 或 -n 标志,patch 命令将每块(hunk)内的信息分别解释成上下文差别、ed 编辑器差别或者正常差别。否则,patch 命令确定基于块(hunk)内信息格式的差别类型。
patch 命令通过获取块(hunk)的首行序号和添加或减去由于应用前一块(hunk)而产生的任何行偏移来搜索位置以应用每一块(hunk)。如果在这一行位置不可能有精确匹配,patch 命令前后搜索以获取与块(hunk)的内容精确匹配的行集合。
如果找不到这些位置,且如果 patch 命令正在应用上下文差异列表,patch 命令能进行非精确搜索。fuzz factor 指定了非精确匹配的行数目。如果模糊因子设置成 1 或者更大,patch 命令执行第二次扫描,这一次忽略上下文的第一行和最后一行。如果没有匹配结果,且最大模糊因子设置成 2 或者更大, patch 命令执行第三次扫描,这一次会忽略上下文的前两行和最后两行。(缺省模糊因子最大值为 2)。如果找不到匹配的位置,patch 命令在拒绝文件中放置块(hunk)。创建拒绝文件时,其名称和输出文件一样,只是在文件名有后缀 .rej。使用 -r 标志可以覆盖此命名约定。
以上下文差异列表格式写拒绝块(hunk),而不管补丁文件的格式如何。如果输入是正常差别或 ed 编辑器样式差别,拒绝文件可能包含上下文格式零行差别。拒绝文件中块(hunk)的行编号可能与补丁文件中的行编号不同。这是因为拒绝文件的行编号反映了新文件而不是老文件中故障块(hunk)的大约位置。
当完成每块(hunk)后,patch 命令会告诉您该块(hunk)是成功还是失败。也可以获知为每块(hunk)假定的新行编号。如果这与差异列表中指定的行编号不同,就会报告偏移量。patch 命令也说明是否使用模糊因子来进行匹配。
注:单一的大偏移可能表示块(hunk)安装位置不正确。模糊因子的使用可能表示布局不正确。
准备补丁
原则
准备将补丁装载给其它用户的程序员应该考虑下面的附加原则:
* 如果想两次应用同一补丁,patch 命令假定第二个应用程序应该是逆向补丁,并且提示确认此逆向。因此,避免发送出这些逆向补丁,因为它使用户疑惑他们是否已经应用了此补丁。
* 建议保留使用最新补丁级别更新的 patchlevel.h 文件。补丁级别可以用作所发送的补丁文件中的第一个差异列表。如果补丁中包含 Prereq: 行,用户不能应用顺序混乱的补丁,同时不收到警告。
* 在上下文差异列表的头中或者使用 Index: 行以确保正确指定了文件名。如果正在子目录中打某些补丁,请确保通知补丁用户在需要时指定 -p 标志。
* 可以通过发送差异列表创建文件,此列表比较一个空文件和想要创建的文件。然而,这个方法只有在想要创建的文件的确不存在于目标目录时才有效。
* 虽然可以将许多差分列表放置到一个文件中,但是将相关补丁分组到单独的文件中会更好。
* patch 命令不能说明 ed 脚本中的行编号是否正确,只能在当它找到更改或删除命令时才能检测正常差异列表中不正确的行编号。使用模糊因子为 3 的上下文差异列表可能有同样的行编号问题。除非添加了一个适当的交互式接口,在这种情形下才使用上下文差异列表来检测更改的正确性。编译无误通常表示补丁工作正常,但是它并不表示没有错误。
* 只有当补丁应用到与生成补丁的完全同一版本的文件中,才保证 patch 命令的结果。
* 如果代码重复,例如:
#ifdef
... NEWCODE
#else
... OLDCODE
# endif
patch 命令不能为两个版本都打补丁。如果 patch 命令成功,它可能补丁了错误版本但是返回了一个成功的退出状态。
标志
-b 在应用差别前保存每个修改后文件的副本。复制的原始文件归档时与原文件同名且添加了后缀 .orig。如果使用那个名称的文件已经存在,它就被覆盖。如果对同一文件应用多个补丁,原始文件只生成一个副本(在第一次补丁时)。如果也指定 -o OutFile 标志,就不会创建 .orig 文件。但是如果指定文件已经存在,就创建 OutFile.orig。
-B Prefix 指定备份文件名称的前缀。此标志只有在和 -b 标志连接使用时才有效。
-c 将补丁文件解释成上下文差异列表(diff -c 或 diff -C 命令的输出)。此标志不能和 -e 或 -n 标志一起使用。
-d Directory 在处理前,更改当前目录到指定目录。
-D Define 使用下面的 C 预处理器构造标记更改:
#ifdef Define
... (NEWCODE)
#else
... (OLDCODE)
#endif /* Define */
Define 变量用作差分符号。此标志只有当正常或上下文格式差异列表用作补丁文件时才有效。
-e 将补丁文件解释成 ed 编辑器脚本。此标志不能和 -c 或 -n 标志一起使用。
-f 禁止查询用户。要禁止注释,使用 -s 标志。
-F Number 设置最大模糊因子。此标志只应用于上下文差异列表,它使 patch 命令在确定块(hunk)的安装位置时忽略指定行编号。如果没有指定 -F 标志,缺省模糊因子为 2。此因子不可以设置成大于上下文差异列表中内容的行的数目(通常为 3)。
注:较大的模糊因子会增加错误补丁的可能性。
-i PatchFile 从指定文件,而不是从标准输入中读取补丁信息。
-l (L 的小写)使差异列表脚本中的任何空格字符序列匹配输入文件中的任何空格字符序列。精确匹配其它字符。
-n 将脚本解释成正常差异列表。此标志不能和 -c 或 -e 标志一起使用。
-N 忽略差别已经向文件应用了的补丁。缺省情况下,会拒绝已经应用的补丁。
-o OutFile 复制要打补丁的文件,然后应用更改,接着将修改版本写到指定的输出文件。单个文件的多个补丁应用于以前补丁所创建的文件的中间版本。因此,多补丁会生成输出文件的多个连接版本。
-p Number 设置路径名的剥离数目,它控制如何处理在补丁文件中找到的路径名称。如果将文件保留在与指定路径不同的目录中,此标志就有用。剥离数目指定了从路径名前去除多少个斜杠。也去除所有中间的目录名。例如,假定补丁文件指定 /u/leon/src/blurf1/blurf1.c:
* -p 0 留下未修改的完整路径名。
* -p 1 除去前导斜杠,留下 u/leon/src/blur
一级方程式锦标赛/blurf1.c。
* -p 4 卸下四个斜杠和三个目录,留下 blurf1/blur
2012年世界一级方程式锦标赛c。
如果没有指定 -p 标志,只使用基本名称(最后的路径名称组件)。此标志只有在没有指定
File 参数时才起作用。
-r RejectFile 覆盖缺省拒绝文件名。通过附加后缀 .rej 到原始文件名中,就形成了缺省拒绝文件名。
-R 逆向补丁脚本理解。例如,如果从新版本到旧版本创建差异列表,使用 -R 标志使 patch 命令在应用前逆向脚本的每个部分。以交换格式保存拒绝差别。 -R 标志不能和 ed 脚本一起使用,因为其中只有很少的信息可以重新构造逆向操作。如果没有指定 -R 标志,patch 命令尝试以逆向理解和正常理解应用每个部分,直到成功应用补丁文件的每一部分。如果尝试成功,提示用户确定是否应该设置 -R 标志。
注:如果此方法和第一个命令是附加命令(就是说,逆序是删除)的正常差异列表一起使用,它就不能检测逆向补丁。因为空上下文无论在何处都匹配,所以附加总是成功的。幸运的是,大多数补丁是添加或更改行而不是删除行。因此大多数逆序的正常差异列表以一个删除开始,它导致故障,并且引起启发(heuristic)。
-s 静默地进行补丁,直到发生错误。
-v 打印修订版头和补丁级别。如果 -v 标志和其它标志一起使用,就忽略其它标志。
-x Number 设置内部调试标志。此标志只适用于 patch 命令开发者。
退出状态
返回下面的出口值:
0 成功完成。
1 产生错误。
示例
1. 要将 difflisting 文件中的差异列表应用到 prog.c 文件,请输入:
patch -i difflisting prog.c
2. 要保存 prog.c 文件的原始版本,请输入:
patch -b -i difflisting prog.c
它将更改应用到 prog.c 并且在 prog.c.orig 文件中保存 prog.c 的原始内容。
3. 要打补丁到 prog.c 文件而不改变原始版本,请输入:
patch -i difflisting -o prog.new prog.c
它将 prog.c 当成源文件使用,但是更改后的版本写到名为 prog.new 的文件中。
文件
/usr/bin/patch 包含 patch 命令。
参考资料
Warning: Invalid argument supplied for foreach() in
/www/wwwroot/newbaike1.com/id.php on line
362