详解Linuxpatch命令参数及⽤法
说到patch命令,就不得不提到diff命令,也就是制作patch的必要⼯具。diff命令,在制作patch⽂件的时候,基本上只需要使⽤到diff -Nau 这个参数,如果⽐较的是⽂件夹,还要加上-r参数,所以⼀般直接使⽤Naur参数。
功能说明:修补⽂件。
语 法:patch [-bceEflnNRstTuvZ][-B <;备份字⾸字符串>][-d <⼯作⽬录>][-D <;标⽰符号>][-F <;监别列数>][-g <;控制数值>][-i <;修补⽂件>][-o <;输出⽂件>][-p <;剥离层级>][-r <;拒绝⽂件>][-V <;备份⽅式>][-Y <;备份字⾸字符串>][-z <;备份字尾字符串>][--backup-if -mismatch][--binary][--help][--nobackup-if-mismatch][--verbose][原始⽂件 <;修补⽂件>] 或 path [-p <;剥离层级>] < [修补⽂件]
补充说明:patch指令让⽤户利⽤设置修补⽂件的⽅式,修改,更新原始⽂件。倘若⼀次仅修改⼀个⽂件,可直接在指令列中下达指令依序执⾏。如果配合修补⽂件的⽅式则能⼀次修补⼤批⽂件,这也是Linux系统核⼼的升级⽅法之⼀。
参 数:
-b或--backup 备份每⼀个原始⽂件。
-B<;备份字⾸字符串>或--prefix=<;备份字⾸字符串> 设置⽂件备份时,附加在⽂件名称前⾯的字⾸字符串,该字符串可以是路径名称。
-c或--context 把修补数据解译成关联性的差异。
-d<⼯作⽬录>或--directory=<⼯作⽬录> 设置⼯作⽬录。
-D<;标⽰符号>或--ifdef=<;标⽰符号> ⽤指定的符号把改变的地⽅标⽰出来。
-e或--ed 把修补数据解译成ed指令可⽤的叙述⽂件。
-E或--remove-empty-files 若修补过后输出的⽂件其内容是⼀⽚空⽩,则移除该⽂件。
-f或--force 此参数的效果和指定-t参数类似,但会假设修补数据的版本为新 版本。
-F<;监别列数>或--fuzz<;监别列数> 设置监别列数的最⼤值。
-g<;控制数值>或--get=<;控制数值> 设置以RSC或SCCS控制修补作业。
-i<;修补⽂件>或--input=<;修补⽂件> 读取指定的修补问家你。
-l或--ignore-whitespace 忽略修补数据与输⼊数据的跳格,空格字符。
-n或--normal 把修补数据解译成⼀般性的差异。
-N或--forward 忽略修补的数据较原始⽂件的版本更旧,或该版本的修补数据已使 ⽤过。
-o<;输出⽂件>或--output=<;输出⽂件> 设置输出⽂件的名称,修补过的⽂件会以该名称存放。
-p<;剥离层级>或--strip=<;剥离层级> 设置欲剥离⼏层路径名称。
-f<;拒绝⽂件>或--reject-file=<;拒绝⽂件> 设置保存拒绝修补相关信息的⽂件名称,预设的⽂件名称为.rej。
-R或--reverse 假设修补数据是由新旧⽂件交换位置⽽产⽣。
-s或--quiet或--silent 不显⽰指令执⾏过程,除⾮发⽣错误。
-t或--batch ⾃动略过错误,不询问任何问题。
-T或--set-time 此参数的效果和指定-Z参数类似,但以本地时间为主。
-u或--unified 把修补数据解译成⼀致化的差异。
-v或--version 显⽰版本信息。
-V<;备份⽅式>或--version-control=<;备份⽅式> ⽤-b参数备份⽬标⽂件后,备份⽂件的字尾会被加上⼀个备份字符串,这个字符串不仅可⽤-z参数变更,当使⽤-V参数指定不同备份⽅式时,也会产⽣不同字尾的备份字符串。
-Y<;备份字⾸字符串>或--basename-prefix=--<;备份字⾸字符串> 设置⽂件备份时,附加在⽂件基本名称开头的字⾸字符串。
-z<;备份字尾字符串>或--suffix=<;备份字尾字符串> 此参数的效果和指定-B参数类似,差别在于修补作业使⽤的路径与⽂件名若为src/linux/fs/super.c,加上backup/字符串后,⽂件super.c会备份于/src/linux/fs/backup⽬录⾥。
-Z或--set-utc 把修补过的⽂件更改,存取时间设为UTC。
--backup-if-mismatch 在修补数据不完全吻合,且没有刻意指定要备份⽂件时,才备份⽂件。
--binary 以⼆进制模式读写数据,⽽不通过标准输出设备。
--help 在线帮助。
--nobackup-if-mismatch 在修补数据不完全吻合,且没有刻意指定要备份⽂件时,不要备份⽂件。
--verbose 详细显⽰指令的执⾏过程。
实验的基本步骤。我打算是建⽴⼀个级联⽬录./x/xx/xxx/,在xxx⽬录下建⽴两个不同的⽂件xxx1,xxx2。然后在xxx⽬录下⽤diff 命令,建⽴⼀个补丁⽂件xxx.patch,在xx⽬录下建⽴⼀个补丁⽂件xx.patch,在x⽬录下建⽴⼀个补丁⽂件x.patch。然后在这三个⽬录下实验。
开始实验:建⽴实验⽬录
[King@Fedora ~]$ mkdir -pv x/xx/xxx
mkdir: 已创建⽬录 “x”
mkdir: 已创建⽬录 “x/xx”
mkdir: 已创建⽬录 “x/xx/xxx”
进⼊xxx⽬录下创建xxx1,xxx2
[King@Fedora ~]$ cd x/xx/xxx
[King@Fedora xxx]$ cat >> xxx1 << EOF
> 111111
> 111111
> EOF
[King@Fedora xxx]$ cat >> xxx2 << EOF
> 111111
> 222222
> EOF
查看这两个⽂件
[King@Fedora xxx]$ diff -y xxx1 xxx2
111111 111111
111111 | 222222
⼀定要注意:打补丁时所在的⽬录
在xxx⽬录下创建补丁⽂件xxx.patch,并查看。
[King@Fedora xxx]$ diff -Naru xxx1 xxx2 > xxx.patch
[King@Fedora xxx]$ cat xxx.patch
- - - xxx1 2009-12-19 22:28:26.582959182 +0800
+++ xxx2 2009-12-19 22:28:42.798928591 +0800
@@ -1,2 +1,2 @@
111111
- 111111
+222222
在xx⽬录下创建补丁⽂件xx.patch,并查看
[King@Fedora xxx]$ cd ..
[King@Fedora xx]$ diff -Naru xxx/xxx1 xxx/xxx2 > xx.patch
[King@Fedora xx]$ cat xx.patch
--- xxx/xxx1 2009-12-19 22:28:26.582959182 +0800
+++ xxx/xxx2 2009-12-19 22:28:42.798928591 +0800
@@ -1,2 +1,2 @@
111111
-111111
+222222
在x⽬录下创建补丁⽂件x.patch,并查看
[King@Fedora xx]$ cd ..
[King@Fedora x]$ diff -Nu xx/xxx/xxx1 xx/xxx/xxx2 > x.patch
[King@Fedora x]$ cat x.patch
--- xx/xxx/xxx1 2009-12-19 22:28:26.582959182 +0800
+++ xx/xxx/xxx2 2009-12-19 22:28:42.798928591 +0800
@@ -1,2 +1,2 @@
111111
-111111
+222222
现将patch⽂件都拷贝到xxx⽬录下去。
[King@Fedora x]$ cp x.patch xx/xxx/
[King@Fedora x]$ cp xx/xx.patch xx/xxx/
进⼊xxx⽬录开始实验
[King@Fedora x]$ cd xx/xxx
[King@Fedora xxx]$ ls
x.patch xx.patch xxx1 xxx2 xxx.patch
[King@Fedora xxx]$ patch-p0< xxx.patch #⽤第⼆个的补丁修改第⼀个⽂件patching file xxx1
[King@Fedora xxx]$ cat xxx1
111111
222222
[King@Fedora xxx]$ patch -RE < xxx.patch #⽤第⼀个的补丁修改第⼀个⽂件
patching file xxx1
[King@Fedora xxx]$ cat xxx1
111111
111111
[King@Fedora xxx]$ patch -p1 < xx.patch
patching file xxx1
[King@Fedora xxx]$ cat xxx1
111111
222222
[King@Fedora xxx]$ patch -RE < xxx.patch
patching file xxx1
[King@Fedora xxx]$ cat xxx1
111111
111111
[King@Fedora xxx]$ patch -p2 < x.patch
patching file xxx1
[King@Fedora xxx]$ cat xxx1
111111
222222
[King@Fedora xxx]$ patch -RE < x.patch
patching file xxx1
[King@Fedora xxx]$ cat xxx1
111111
111111
------------------------------------------------------------
[King@Fedora xx]$ patch-p0 < xx.patch # ⽤第⼆个的补丁修改第⼀个⽂件
patching file xxx1
[King@Fedora xxx]$ cat xxx1
111111
222222
[King@Fedora xxx]$ patch -RE < xxx.patch #⽤第⼀个的补丁修改第⼀个⽂件
patching file xxx1
[King@Fedora xxx]$ cat xxx1
111111
111111
[King@Fedora xxx]$ patch -p1 < x.patch
patching file xxx1
[King@Fedora xxx]$ cat xxx1
111111
222222
[King@Fedora xxx]$ patch -RE < xxx.patch
patching file xxx1
[King@Fedora xxx]$ cat xxx1
111111
111111
-
-------------------------------------------------------------------------
[King@Fedora x]$ patch-p0< x.patch # ⽤第⼆个的补丁修改第⼀个⽂件
patching file xxx1
[King@Fedora xxx]$ cat xxx1
111111
222222
[King@Fedora xxx]$ patch -RE < xxx.patch #⽤第⼀个的补丁修改第⼀个⽂件
patching file xxx1
[King@Fedora xxx]$ cat xxx1
111111
111111
这⾥唯⼀需要说明的是p0的含义,因为在x.patch补丁⽂件⾥的路径信息是这样的:
--- xx/xxx/xxx1
p表⽰跳过⼏级⽬录,因为是在x⽬录下使⽤的patch命令,xx⽬录就在x⽬录下,所以不必跳过任何⽬录,⽽应该使⽤---xx/xxx/xxx1 完整路径,所以此时使⽤的是p0。
注意:patch -p后⾯是不能带负数的。不使⽤p参数的时候,patch命令会忽略任何⽬录,直接使⽤⽂件。
[King@Fedora x]$ patch x/xx/xxx/xxx1 < x.patch # ⽤补丁x.patch 直接修改⽂件xxx1,因为没有⽤p参数,所以会忽略掉补丁⽂件⾥的所有⽬录。
作为程序员,了解diff&patch命令是⾮常必要的。⽐如说我们发现某个项⽬有bug代码,⽽⾃⼰⼜没有提交权限,那么此时最合适的解决⽅法就是⽤diff命令做⼀个补丁发给项⽬成员。项⽬成员通过patch命令可以⽴刻知道你的意图。有⼈会说直接传⼀个新⽂件不是更简单?不要忘了,⼀个patch⽂件尺⼨更⼩传输更快,⽽且可以明显的看到都做了哪些修改。
保证当前⽬录是demo名录:
# mkdir demo
# cd demo
先模拟⼀个项⽬⽬录old:
# mkdir -p old/a/b
# vi old/a/
old_line_1
old_line_2
假设我们发现项⽬old有bug代码,下⾯我们先拷贝⼀个新⽬录new,并在此修改bug代码:
# cp -r old new
# vi new/a/
new_line_1
new_line_2
保证old和new两个⽬录都在当前⽬录下,下⾯就可以使⽤diff命令了,不要使⽤绝对路径,⽽应该使⽤相对路径,⾄于原因,看到⽂章结尾你就清楚了:
# LC_ALL=C TZ=UTC0 diff -Naur old new > foo.patch
如果不在意字符集,时差等问题,也可以省略LC_ALL=C TZ=UTC0环境变量:
# diff -Naur old new > foo.patch
内容来⾃Linuxren.NET
其中-Naur参数属于固定⽤法,⼤多数时候,在使⽤diff命令时搭配这个参数就可以了。
⼤概浏览⼀下补丁⽂件:
# cat foo.patch
diff -Naur old/a/ new/a/
--- old/a/ 2009-12-07 20:40:07.000000000 +0800
+++ new/a/ 2009-12-07 20:41:51.000000000 +0800
@@ -1,2 +1,2 @@
-old_line_1
-old_line_2
+new_line_1
+new_line_2
加减号后⾯的内容是有⽤的内容,其他的内容是⽅便你查阅的相关信息内容,补丁制作完成。
此时的⽂件⽬录结构⼤概如下所⽰:
#tree
demo
|-- old
| `-- a
| `-- blinux登录命令
| `--
|-- new
| `-- a
| `-- b
| `--
-- foo.patch
下⾯看看如何使⽤patch来应⽤补丁,要注意的是当前⽬录是demo,试试下⾯命令:
# patch -p0 < foo.patch
patching file old/a/
这⾥唯⼀需要说明的是p0的含义,因为在foo.patch补丁⽂件⾥的路径信息是这样的:
-
-- old/a/
p表⽰跳过⼏级⽬录,因为是在demo⽬录下使⽤的patch命令,old⽬录就在demo⽬录下,所以不必跳过任何⽬录,⽽应该使⽤old/a/完整路径,所以此时使⽤的是p0。
查看⼀下⽬标⽂件,你会发现内容已经修改成新的了:
# cat old/a/
new_line_1
new_line_2
此时如果你再次使⽤patch命令,系统会问你是否想还原,输⼊y 还原:
# patch -p0 < foo.patch
patching file old/a/
Reversed (or previously applied) patch detected! Assume -R? [n] y
查看⼀下⽬标⽂件,你会发现内容已经还原成旧的了:
# cat old/a/
old_line_1
old_line_2
如果你想严格指定是应⽤补丁可以使⽤下⾯命令(就是增加N参数):
# patch -Np0 < foo.patch
如果你想严格指定是还原补丁可以使⽤下⾯命令(就是增加R参数):
# patch -Rp0 < foo.patch
注释:在本例中,每次应⽤补丁后,⾃⼰还原补丁,以备后⽤继续试验,我就不多说了。
看到这⾥如果你对patch的p参数还不太清楚的话,接着往下看,我们改变⼀下当前路径:
# cd old
此时就应该是p1,⽽不是p0了,引⽤foo.patch⽂件的路径也要相对变⼀下,因为当前⽬录已经是old了: Linuxren.Net
# patch -p1 < ../foo.patch
patching file a/
因为此时我们是在old下使⽤patch命令,和a⼦⽬录平级,⽽补丁⽂件foo.patch⾥的路径声明是:
--- old/a/
也就是说第⼀个斜线左边的old/部分已经没⽤了,这就是p1的含义!
继续往深度变换路径,依次测试使⽤p2,p3参数:
# cd a
# patch -p2 < ../../foo.patch
patching file
# cd b
# patch -p3 < ../../../foo.patch
patching
在本例中,p3已经是最深⽬录了,此时可以省略p参数:
# patch < ../../../foo.patch
patching
也就是说,不使⽤p参数的时候,patch命令会忽略任何⽬录,直接使⽤⽂件。
下⾯接着⽂章前⾯说的为什么使⽤diff命令时最好不要使⽤绝对路径,⽽应该使⽤相对路径?
答:如果你在使⽤diff的时候使⽤的是绝对路径,那么补丁⽂件⾥的⽂件路径信息会类似下⾯的样⼦:
--- /a/b/c/d/e/f/
如此⼀来,当别⼈想应⽤你的补丁时,因为⽬录结构肯定有差异,所以就不得不费⼒判断到底使⽤p⼏。这样⼀来就很容易出错,相反,如果使⽤相对路径的话,⼤多数时候,p0或者p1就⾜够了,不易出错。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论