1、命令简介
patch:用于应用补丁文件到源代码文件,以实现更新或修复源代码的功能。通常,开发者和维护者会创建补丁文件,以便将代码的更改传播给其他人或将更改应用到不同的代码库。
2、命令语法
patch [options] [originalfile [patchfile]]
但通常情况下:
patch -pnum <patchfile
3、命令描述
patch
接受一个由 diff
程序生成的差异列表的补丁文件 patchfile
,并将这些差异应用于一个或多个原始文件,从而生成修补后的版本。通常,修补后的版本会取代原始版本。可以制作备份;请参见 -b
或 --backup
选项。要修补的文件名通常来自补丁文件,但如果只有一个要修补的文件,它可以在命令行上指定为 originalfile
。
启动时,patch
尝试确定差异列表的类型,除非 -c
(--context)、-e
(--ed)、-n
(--normal) 或 -u
(--unified) 选项进行了覆盖。上下文差异(旧式、新式和统一)和普通差异由 patch
程序本身应用,而 ed 差异则通过管道简单地传送给 ed(1) 编辑器。
patch 试图跳过任何前导垃圾,应用差异,然后跳过任何尾随垃圾。因此,您可以将包含差异列表的文章或消息提供给 patch,它应该能工作。如果整个差异都有一个一致的缩进,或者一个上下文差异包含以 CRLF 结尾的行,或者通过在以 "-" 开头的行前加上 "- " 来一次或多次封装,如 Internet RFC 934 所指定的,这都会被考虑进去。
对于上下文差异,以及在较小的程度上对于普通差异,patch 可以检测补丁中提到的行号是否正确,并尝试找到正确的位置来应用每一块补丁。首先,它采用为这块指定的行号,再加上或减去在应用前一块时使用的任何偏移量。如果那不是正确的位置,patch 会前后扫描寻找与块中给出的上下文匹配的行集合。首先,patch 寻找所有上下文行都匹配的地方。如果找不到这样的地方,且它是一个上下文差异,且最大模糊因子设置为1或更大,则忽略上下文的第一行和最后一行进行另一次扫描。如果失败,且最大模糊因子设置为2或更大,忽略上下文的前两行和最后两行进行另一次扫描。(默认的最大模糊因子是2)如果 patch 找不到一个地方来安装那个补丁块,它会将这块输出到一个拒绝文件,该文件通常是输出文件名加上 .rej
后缀,或者如果 .rej
生成的文件名太长则为 #(如果连加上单个字符 # 都使文件名太长,那么 # 就会替换文件名的最后一个字符)。(被拒绝的块以普通的上下文差异形式输出,不论输入的补丁形式如何。如果输入是普通的差异,许多上下文简单地为空。)拒绝文件中的块上的行号可能与补丁文件中的不同:它们反映了 patch
认为失败的块在新文件中的大致位置,而不是旧文件中的位置。
每当完成一块时,都会告诉您这块是否失败,如果失败,patch
认为这块应放在新文件的哪一行。如果块安装在与差异中指定的行号不同的行上,您会被告知偏移量。一个很大的偏移量可能表明一个块被安装在了错误的位置。如果使用了模糊因子来进行匹配,您也应该有点怀疑。如果给出了 --verbose
选项,还会告诉您完全匹配的块。
如果命令行上没有指定原始文件 origfile
,patch
会尝试从前导垃圾中找出要编辑的文件的名称,使用以下规则。
首先,patch
按如下方式获取一个有序的候选文件名列表:
参数 | 描述 |
o | 如果头部是上下文差异的头部, patch 将使用头部中的旧文件名和新文件名。 如果一个文件名没有足够多的斜杠以满足 -pnum 或 --strip=num 选项, 则会被忽略。文件名 /dev/null 也会被忽略。 |
o | 如果在前导垃圾中存在一个 Index: 行, 并且旧文件名和新文件名都不存在, 或者如果 patch 符合 POSIX, patch 将使用 Index: 行中的文件名。 |
o | 为了以下规则的目的, 候选文件名被认为是按顺序 (旧文件、新文件、索引), 而不考虑它们在头部中出现的顺序。 |
然后,patch 根据以下方式从候选列表中选择一个文件名: | |
o | 如果某些命名文件存在, 则如果符合 POSIX, patch 将选择第一个文件名, 否则将选择最佳文件名。 |
o | 如果 patch 没有忽略 RCS、ClearCase 和 SCCS(参见 -g num 或 --get=num 选项), 而且没有命名的文件存在, 但找到了 RCS、ClearCase 或 SCCS 主文件, 则 patch 将选择具有 RCS、 ClearCase 或 SCCS 主文件的第一个命名文件。 |
o | 如果没有命名的文件存在,没有找到 RCS、 ClearCase 或 SCCS 主文件, 提供了一些文件名,patch 不符合 POSIX, 并且补丁似乎创建了一个文件, 则 patch 将选择需要创建最少目录的最佳文件名。 |
o | 如果以上启发法没有结果产生文件名, 则将询问您要修补的文件的名称, 然后 patch 将选择该名称。 |
为了确定非空文件名列表中的最佳文件名,patch 首先选择所有具有最少路径名组件的名称;然后,它选择所有具有最短基本名称的名称;然后,它选择所有最短的名称;最后,它选择第一个剩余的名称。此外,如果前导垃圾包含 Prereq: 行,patch 将从先决条件行中获取第一个单词(通常是版本号),然后检查原始文件,看看是否可以找到该单词。如果找不到,patch 在继续之前会要求确认。
总之,这意味着您应该能够在新闻界面中执行以下操作:
patch -d /usr/src/local/blurfl
然后直接从包含补丁的文章中对 blurfl
目录中的文件进行修补。
如果补丁文件包含多个补丁,patch
会尝试将它们中的每一个应用,就好像它们来自不同的补丁文件一样。这意味着,除其他事项外,假定必须为每个 diff 列表确定要修补的文件的名称,并且在每个 diff 列表之前的垃圾包含有趣的内容,例如文件名和修订级别,如前面提到的。
4、命令选项
选项 | 描述 |
-b or --backup | 创建备份文件。也就是说,在修补文件时, 重命名或复制原始文件, 而不是删除它。如果要备份一个不存在的文件, 将创建一个空的、不可读的备份文件 作为占位符来表示不存在的文件。 有关备份文件名称的确定方式, 请参阅-V或--version-control选项。 |
--backup-if-mismatch | 如果补丁与文件不完全匹配且没有其他备份请求, 则备份文件。这是默认设置,除非 patch 符合POSIX标准。 |
--no-backup-if-mismatch | 如果补丁与文件不完全匹配且没有其他备份请求, 则不备份文件。 这是 patch 符合POSIX标准的默认设置。 |
-B pref or --prefix=pref | 生成简单备份文件名称时,在文件名前缀pref 。 例如,使用
的简单备份文件名称为 |
--binary | 以二进制模式读取和写入所有文件, 除了标准输出和 该选项对符合POSIX标准的系统没有影响。 在像DOS这样的系统上, 该选项会产生差异,补丁应该由
|
-c or --context | 将补丁文件解释为普通上下文差异。 |
-d dir or --directory=dir | 在执行任何其他操作之前,立即切换到目录dir。 |
-D define or --ifdef=define | 使用 结构标记更改,其中
|
--dry-run | 在实际更改任何文件之前, 打印应用补丁的结果。 |
-e or --ed | 将补丁文件解释为ed脚本。 |
-E or --remove-empty-files | 删除在应用补丁后为空的输出文件。 通常情况下,这个选项是不必要的,因为 patch 可以检查头部的时间戳来确定 是否应该在应用补丁后存在文件。 但是,如果输入不是上下文差异,或者 patch 符合POSIX标准,那么除非使用此选项, 否则 patch 不会删除空的已修补文件。 当 patch 删除一个文件时, 它还会尝试删除任何空的祖先目录。 |
-f or --force | 假设用户完全了解自己在做什么, 不要询问任何问题。跳过那些头部 没有指定要修补哪个文件的补丁; 即使补丁的版本与补丁中的Prereq: 行不匹配也要修补文件;并假设补丁没有反转, 即使看起来是反转的也一样。 这个选项不会抑制评论; 可以使用-s选项来实现。 |
-F num or --fuzz=num | 设置最大模糊因子。 此选项仅适用于具有上下文的差异,并导致 patch 在查找要安装hunk的位置时 忽略多达这么多行。请注意, 更大的模糊因子会增加出现错误补丁的机会。 默认的模糊因子是2, 通常不应设置为大于上下文差异中上下文行数的数量,通常为3。 |
-g num 或 --get=num | 当文件受RCS或SCCS控制 并不存在或者是只读的且匹配默认版本时, 或当文件在ClearCase控制下并不存在时, 控制patch的动作。如果 num 是正数, patch 从版本控制系统中获取(或检出)文件; 如果为0, patch 忽略RCS、ClearCase 和SCCS并不获取文件;如果为负数, patch 会询问用户是否获取文件。 默认值取决于PATCH_GET环境变量, 否则与POSIX一致时为0,否则为负数。 |
--help | 打印选项摘要并退出。 |
-i patchfile 或 --input=patchfile | 从 patchfile 中读取补丁。 如果 patchfile 是 ,则从标准输入中读取。 |
-l 或 --ignore-whitespace | 宽松匹配,当文件中的制表符或空格被修改时。 在补丁文件中的任何空格序列都 与原始文件中的任何序列匹配, 行尾的空格序列被忽略。 其他字符必须精确匹配。 |
-n 或 --normal | 将补丁文件解释为常规差异。 |
-N 或 --forward | 忽略看似是反向或已经应用的补丁。 也可查看 -R选项。 |
-o outfile 或 --output=outfile | 将输出发送到 outfile 而不是直接在文件中打补丁。 |
-pnum 或 --strip=num | 从补丁文件中找到的每个文件名中去除包含 num 个前导斜杠的最小前缀。 一系列相邻的斜线被计为一个斜线。 这控制如何处理在补丁文件中找到的文件名, 以防您保持的文件目录与发送补丁的人不同。 |
--posix | 更严格地遵循POSIX标准,具体为: 从列表(旧的、新的、索引)中 选择第一个存在的文件; 不删除打补丁后为空的文件; 不询问是否从RCS、ClearCase或SCCS获取文件; 要求所有选项都在命令行中的文件之前; 当有不匹配时,不备份文件。 |
--quoting-style=word | 使用 word 样式来引用输出名称。 有效的值包括:literal(原样输出)、 shell(如果名称包含shell元字符或 可能导致输出模糊则引用)、shell-always (总是为shell引用名称)、 c(引用名称如C语言字符串)、 escape(与c相似,但不包括双引号)。 默认值可以通过QUOTING_STYLE环境变量指定。 如果未设置该变量,默认值为shell。 |
-r rejectfile 或 --reject-file=rejectfile | 将拒绝放入 rejectfile 而不是默认的 |
-R 或 --reverse | 假设此补丁是在旧文件和新文件交换后创建的。 patch试图在应用每个块之前交换它们。 拒绝采用交换格式输出。 -R 选项不支持ed差异脚本。 |
-s 或 --silent 或 --quiet | 除非出现错误,否则静默工作。 |
-t 或 --batch | 压制类似于 -f 的问题, 但做一些不同的假设:跳过其头部不包含文件名的补丁; 跳过文件版本与补丁中的Prereq:行不匹配的补丁;如 果看起来是这样,则假设补丁是反向的。 |
-T 或 --set-time | 根据上下文差异头中给出的时间戳 设置打补丁文件的修改和访问时间, 假设上下文差异头使用本地时间。 |
-u 或 --unified | 将补丁文件解释为统一的上下文差异。 |
-v 或 --version | 打印出patch的修订头和patch级别,并退出。 |
-V method 或 --version-control=method | 使用方法确定备份文件名。 此方法也可以通过PATCH_VERSION_CONTROL环境变量 (或,如果未设置,则为VERSION_CONTROL环境变量)给出, 并被此选项覆盖。 |
--verbose | 输出关于正在进行的工作的额外信息。 |
-x num 或 --debug=num | 设置仅对补丁修补者感兴趣的内部调试标志。 |
-Y pref 或 --basename-prefix=pref | 当生成其简单备份文件名时, 将 pref 前缀添加到文件名的基名。 |
-z suffix 或 --suffix=suffix | 使用 suffix 作为简单备份后缀。 |
-Z 或 --set-utc | 根据上下文差异头中给出的时间戳 设置打补丁文件的修改和访问时间, 假设上下文差异头使用协调世界时(UTC)。 |
5、使用示例
1)应用补丁文件
patch < patchfile
从标准输入中读取补丁文件(patchfile)并将其应用于当前目录中的文件。
2)指定要应用补丁的目标文件
patch -i patchfile
从名为patchfile的文件中读取补丁并将其应用于当前目录中的文件。
3)指定要应用补丁的目标文件和目录
patch -i patchfile -d /path/to/directory
从名为patchfile的文件中读取补丁并将其应用于位于/path/to/directory目录中的文件。
4)显示补丁操作的详细信息
patch -p1 --verbose -i patchfile
以详细模式应用补丁,并将补丁文件中的相对路径中的第一个目录级别(-p1)去除。
5)忽略空格差异并应用补丁
patch -l -i patchfile
-l
选项将使patch忽略补丁文件和原始文件中的空格差异。
6)备份原始文件并应用补丁
patch -b -i patchfile
-b
选项将在应用补丁时创建原始文件的备份副本。
7)应用多个补丁文件
patch -i patchfile1 -i patchfile2