linux diff与patch的使用


diff与patch的命令语法
diff(differential)
功能说明:比较文件的差异。
语法:diff [-abBcdefHilnNpPqrstTuvwy][-<行数>;][-C <行数>;][-D <巨集名称>;][-I <字符或字符串>;][-S <文件>;][-W <宽度>;][-x <文件或目录>;][-X <文件>;][--help][--left-column][--suppress-common-line][文件或目录1][文件或目录2]
补充说明:diff以逐行的方式,比较文本文件的异同处。所是指定要比较目录,则diff会比较目录中相同文件名的文件,但不会比较其中子目录。
参数:
-<行数>; 指定要显示多少行的文本。此参数必须与-c或-u参数一并使用。
-a或--text diff预设只会逐行比较文本文件。
-b或--ignore-space-change 不检查空格字符的不同。
-B或--ignore-blank-lines 不检查空白行。
-c 显示全部内文,并标出不同之处。
-C<行数>;或--context<行数>; 与执行"-c-<行数>;"指令相同。
-d或--minimal 使用不同的演算法,以较小的单位来做比较。
-D<巨集名称>;或ifdef<巨集名称>; 此参数的输出格式可用于前置处理器巨集。
-e或--ed 此参数的输出格式可用于ed的script文件。
-f或-forward-ed 输出的格式类似ed的script文件,但按照原来文件的顺序来显示不同处。
-H或--speed-large-files 比较大文件时,可加快速度。
-l<字符或字符串>;或--ignore-matching-lines<字符或字符串>; 若两个文件在某几行有所不同,而这几行同时都包含了选项中指定的字符或字符串,则不显示这两个文件的差异。
-i或--ignore-case 不检查大小写的不同。
-l或--paginate 将结果交由pr程序来分页。
-n或--rcs 将比较结果以RCS的格式来显示。
-N或--new-file 在比较目录时,若文件A仅出现在某个目录中,预设会显示:
Only in目录:文件A若使用-N参数,则diff会将文件A与一个空白的文件比较。
-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=<列数>; 以合并的方式来显示文件内容的不同。
-v或--version 显示版本信息。
-w或--ignore-all-space 忽略全部的空格字符。
-W<宽度>;或--width<宽度>; 在使用-y参数时,指定栏宽。
-x<文件名或目录>;或--exclude<文件名或目录>; 不比较选项中所指定的文件或目录。
-X<文件>;或--exclude-from<文件>; 您可以将文件或目录类型存成文本文件,然后在=<文件>;中指定此文本文件。
-y或--side-by-side 以并列的方式显示文件的异同之处。
--help 显示帮助。
--left-column 在使用-y参数时,若两个文件某一行内容相同,则仅在左侧的栏位显示该行内容。
--suppress-common-lines 在使用-y参数时,仅显示不同之处。
patch(打补丁)命令使用详解
功能说明:修补文件。
语法: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 详细显示指令的执行过程。
接下来将会对diff与patch的具体用法做比较深入的分析
两个文件夹比较:diff -urNa dir1 dir2 > file.diff
diff的输出格式分为传统格式和统一格式
1)diff的传统格式输出
############################################
cat before.txt
输出:
This is a line to be deleted
This is a line that will be changed
This is a line that will be unchanged
cat after.txt
输出:
This is a line that has been changed
This is a line that will be unchanged
This is a line that has been added
############################################
diff before.txt after.txt
输出:
1,2c1
< This is a line to be deleted
< This is a line that will be changed
---
> This is a line that has been changed
3a3
> This is a line that has been added
############################################
注释:
传统格式的输出
1,2c1是指替换第1个文件的第1,2行到第2个文件的第2行,这里的1,2是指第1个文件的第1,2行,c是替换的意思,最后的1是第2个文件的第1行
<号是指第1个文件更改或删除的行
---号是分割两个文件
>号是第2个文件中增加或删除的行
3a3是指将第2个文件的第3行插入到第一个文件的第3行
也就是说第1个文件的:
< This is a line to be deleted
< This is a line that will be changed
被替换成第2个文件的:
> This is a line that has been changed
由于第1个文件的第3行和第2个文件的第2行一致,所以不做修改.
由于第2个文件的第3行是第1个文件所不具有的,所以在第1个文件的最后一行增加:
> This is a line that has been added
2)patch命令的应用
用diff的传统格式输出:
#################################
diff before.txt after.txt >mypatch.txt
#################################
用patch修补before.txt文件,使before.txt和after.txt一致.
#################################
cat mypatch.txt |patch before.txt
输出:
patching file before.txt
#################################
比较两个文件,现在是一致的了.
#################################
cmp before.txt after.txt
#################################
用patch命令恢复before.txt.
#################################
patch -R before.txt <mypatch.txt
输出:
patching file before.txt
#################################
注:-R标记告诉patch在反向上应用区别或者撤销patch.
再比较两个文件,现在不一致了.
#################################
cmp before.txt after.txt
输出:
before.txt after.txt differ: byte 17, line 1
#################################
3)diff的统一格式输出
#################################
diff -u before.txt after.txt |tee mypatch.diff
输出:
--- before.txt 2009-06-20 05:21:49.000000000 +0800
+++ after.txt 2009-06-20 04:03:16.000000000 +0800
@@ -1,3 +1,3 @@
-This is a line to be deleted
-This is a line that will be changed
+This is a line that has been changed
This is a line that will be unchanged
+This is a line that has been added
#################################
注释:
diff -u选项是统一格式输出.
--- before.txt 2009-06-20 05:21:49.000000000 +0800
--- before.txt是指旧文件
+++ after.txt 2009-06-20 04:03:16.000000000 +0800
+++ after.txt是指新文件.
@@ -1,3 +1,3 @@
@@ -1,3是指第1个文件一共有3行,+1,3 @@是指第2个文件一共有3行.
-This is a line to be deleted
-This is a line that will be changed
是被删除的行
+This is a line that has been changed
是增加的行
This is a line that will be unchanged
没有-号和+号是指该行不变,因为after.txt和before.txt都有这行.
+This is a line that has been added
是增加的行
diff的统一格式比较与输出是按顺序进行的.
4)diff命令在目录中的应用
新建old和new目录,old目录包含了初始内容,new目录包含文件的最新版本.
##########################################
mkdir old new
echo "This is one. It's unchanged." | tee old/one new/one
echo "This is two. It will change." > old/two
echo "This is two. It changed.">new/two
echo "This is three. It's new" > new/three
##########################################
创建修补文件
##########################################
diff -Nur old/ new/ >mypatch.diff
##########################################
注:-r选项按照文件目录递归创建修补文件.
-u还是统一模式
-N是指当diff遇到一个只存在于两个树中的一个树中的文件时,默认情况下跳过文件并且打印一个警告到stderr.
这个行为可以通过-N选项来更改,这也导致了diff认为丢失的文件实际上是存在的,但它是空的.采用这种方式,
一个修补文件可以包括已经创建的文件.然后应用修补程序创建新的文件.
##########################################
more mypatch.diff
输出:
diff -Nur old/three new/three
--- old/three 1970-01-01 08:00:00.000000000 +0800
+++ new/three 2009-06-20 06:55:34.000000000 +0800
@@ -0,0 +1 @@
+This is three. It's new
diff -Nur old/two new/two
--- old/two 2009-06-20 06:55:08.000000000 +0800
+++ new/two 2009-06-20 06:55:21.000000000 +0800
@@ -1 +1 @@
-This is two. It will change.
+This is two. It changed.
##########################################
注释:
diff -Nur old/three new/three是指下面比较old/three new/three两个文件.
因为没有old/three文件,所以在old/three中增加+This is three. It's new
diff -Nur old/two new/two是指下面比较old/two new/two两个文件
因为old/two与new/two的第3行不一致,所以删除This is two. It will change.增加This is two. It changed.
打补丁到old目录,新建old/three以及更改old/two
##########################################
patch --dir old< mypatch.diff
ls -l old/
输出:
one three two
##########################################
恢复old目录的内容,包括删除old/three,以及恢复old/two文件
##########################################
patch --dir old -R <mypatch.diff
输出:
ls -l old/
one two
##########################################
5)检查和合并更改
用vim突出显示单个字符的更改来表示区别.
##########################################
vim -d after.txt before.txt
##########################################
用gui工具gvimdiff来显示两个文件.
##########################################
gvimdiff after.txt before.txt
##########################################
新建文件orig.c
##########################################
vi orig.c
void foo(void)
{
printf("This will be changed by me. /n");
printf("This will be unchanged,/n");
printf("This will be changed by you./n");
}
##########################################
复制文件orig.c到me.c,更改第4行为printf("This was changed by me. /n");
##########################################
vi me.c
void foo(void)
{
printf("This was changed by me. /n");
printf("This will be unchanged,/n");
printf("This will be changed by you./n");
}
##########################################
复制文件orig.c到you.c,更改第7行为printf("This was changed by you./n");
##########################################
vi you.c
void foo(void)
{
printf("This will be changed by me. /n");
printf("This will be unchanged,/n");
printf("This was changed by you./n");
}
##########################################
版本工具如cvs,subversion使用GNU合并工具称为diff3.
##########################################
diff3 me.c orig.c you.c
输出:
====1
1:3c
printf("This was changed by me. /n");
2:3c
3:3c
printf("This will be changed by me. /n");
====3
1:7c
2:7c
printf("This will be changed by you./n");
3:7c
printf("This was changed by you./n");
注:
在没有参数的情况下,diff3产生的输出说明了那行更改.
====1和====3指明造成同原始文件不同的是哪一个修改文件.
编号方式基于参数序列.
也就是第1个文件和第3个文件与原文件不同.
1:3c
printf("This was changed by me. /n");
3:3c
printf("This will be changed by me. /n");
1:3c表示第1个文件的第3行与3:3c表示的第3个文件的第3行不同.
为什么不显示与原文件的比较呢。因为第3个文件的第3行与源文件(第2个文件)相同.所以与哪个文件比较无所谓了.
2:7c
printf("This will be changed by you./n");
3:7c
printf("This was changed by you./n");
2:7c表示第2个文件的第7行与3:7c表示的第3个文件的第7行不同.
diff3会试图为我们进行合并.合并是在源文件的基础上,依据两个新文件进行修改
源文件是第二个文件,第一个文件和第三个文件可以互换,但他们必须有共同的祖先,就是第二个文件.
#######################################
diff3 -m me.c orig.c you.c |cat -n
输出:
1 void foo(void)
2 {
3 printf("This was changed by me. /n");
4
5 printf("This will be unchanged,/n");
6
7 printf("This was changed by you./n");
8 }
########################################
为了测试更复杂的环境,新建一个文件orig.c.1
内容如下:
########################################
vi orig.c.1
void foo(void)
{
printf("This will be changed by both of us./n");
}
########################################
用diff3 -m再次比较输出,如下:
########################################
diff3 -m me.c orig.c.1 you.c
void foo(void)
{
<<<<<<< me.c
printf("This was changed by me. /n");
printf("This will be unchanged,/n");
printf("This will be changed by you./n");
||||||| orig.c.1
printf("This will be changed by both of us./n");
=======
printf("This will be changed by me. /n");
printf("This will be unchanged,/n");
printf("This was changed by you./n");
>>>>>>> you.c
}
########################################
注释:以上的格式,同cvs update,需要人工合并文件的格式是一致的。
diff实用程序带上-u(unified output format,统一输出格式)选项后,执行结果将首先说明要比较的两个文件,其中一个用正号(+)表示,另一个用负号(-)表示。如图3-8所示,负号代表文件color.1,正号代表文件color.2。
命令diff -u将具有多行的较长文件分成几块。每块前面一行的开始和结束都用符号“@@”标识,其中的数字表明了块中每个文件的起始行编号和行数,数字–1和6表明该块从文件color.1(由负号指明)的第1行到第6行,数字+1和5表明该块包括从color.2的第1行到第5行。
$ diff -u colors.1 colors.2
--- colors.1 2012-04-05 10:12:12.322528610 -0700
+++ colors.2 2012-04-05 10:12:18.420531033 -0700
@@ -1,6 +1,5 @@
red
+blue
green
yellow
-pink
-purple
orange
diff在统一输出格式下的比较结果
在这些头部信息之后,命令diff -u显示了几行文本信息,有的行始于正号,有的行始于负号,有的行正负号都没有(起始于空格)。带正号的行表明其仅出现在正号代表的文件内,带负号的行表明其仅出现在负号代表的文件内,正负号都没有的行表示其出现在两个文件的相同位置。
patch制作及打patch
1,如何制作补丁patch文件
patch文件也叫补丁,就是一个文本文档,这个文档包含了在两个不同版本的源代码树之间的变化。补丁是通过diff应用程序来创建的。为了正确地打上一个补丁,你需要知道这个补丁是从哪个基础版本产生出来的以及这个补丁将要把目前的源代码树变化到什么新的版本。这些信息或者会出现在补丁文件的原数据中,或者可能从文件名中推断出来。
diff 命令的用法
1、"-u":表示在比较结果中输出上下文中一些相同的行,这有利于人工定位
2、"-r":表示递归比较各个子目录下的文件
3、"-N":将不存在的文件当作空文件
4、"-w":忽略对空格的比较
5、"-B":忽略对空行的比较
6、 -a或--text:预设只会逐行比较文本文件;
比如基于kernel内核做了修改,修改lcd 代码,修改前的内容放在文件夹kernel下,修改后的内容放在文件夹kernel_new下,那么制作patch文件的命令为:
~/sourcecode/$diff -Naur kernel/ kernel_new/ >lcd.patch
2,怎样打补丁patch和卸载补丁patch
可以使用patch程序来打一个补丁。patch程序读取一个diff(或者patch)文件,然后把文件中描述的变化内容应用到代码树上。Linux内核中的补丁是相对于保存内核源代码目录的父目录而生成的。这就意味着:patch文件中的文件路径包含了它所基于的内核源文件目录的名字(或者像是"a/"和"b/"之类的其它名字)。
由于这很可能和你本地机器上的内核源代码目录的名字不匹配。你应该切换到你的内核源代码目录,并且在打补丁的时候去掉patch中文件名字路径的第一个分量(patch命令的-p1参数可以完成这个任务)。为了卸载掉一个以前已经打上的补丁,使用-R参数来打补丁。于是,如果你使用如下的命令来打补丁:
patch -p1
那么你可以像下面这样来卸载掉这个补丁:
patch -R -p1
例如其他人下载到上面提供的patch文件后,只需在标准的kernel内核目录里执行
~/sourcecode/kernel/$patch -p1<../zwx-lcd.patch
这里假设zwx-lcd.patch和kernel文件夹是在同一目录下,且上述命令 在kernel文件夹内执行
如果在/sourcecode目录下面执行命令
~/sourcecode/$patch -p0<../zwx-lcd.patch
patch,是打补丁的命令,有很多用法,详见帮助#man patch。
-p参数决定了是否使用读出的源文件名的前缀目录信息,不提供-p参数,则忽略所有目录信息,
patch -p0 (“p"指的是路径,后面的数字表示去掉路径的第几部分。0,表示不去掉,为全路径)
patch -p1 (“p"后面的数字1,表示去掉前第一个路径,第一个"/"以前的目录,依此类推。
如/usr/src/linux-2.6.11/Makefile这样的文件名,在提供-p3参数时将使用linux-2.6.11/Makefile作为所要patch的文件。
对于刚才举的Linux内核源码LCD升级包的例子,假定源码目录位于/home/freeoa/sourcecode/kernel中,则在当前目录为/home/freeoa/sourcecode/时使用"patch -p0<../zwx-lcd.patch"可以工作,在当前目录为/home/freeoa/sourcecode/kernel时,使用"patch -p1<../zwx-lcd.patch"也可以正常工作。
如果patch文件里面描述的第一级目录和你自己的第一级目录名字不一样,要将第一级的目录去掉,这个方法就派上用场了。比如如果你拿到的patch描述的目录和你的不一样,patch第一行描述的目录信息
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
但是你的目录既不是a,也不是b,那么你就要将目录的第一层去掉,到你的kernel的路径下面打patch用-p1参数
diff可以完成比较功能,生成补丁文件。
格式:diff [option] oldfile newfile
常用的option选项有:
-r 对目录进行递归处理
-u 输出统一格式,diff有"传统"和"统一"两种格式,现在一般使用"统一"格式,比较而言,统一格式生成的文件大,但包含了更多的信息,有利于阅读与定位
-N 补丁中包含整个新文件
-a 补丁中包含二进制文件
缺省时,diff向标准输出打印,所以一般都重定向到文件并以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 命令失败或拒绝接受补丁时,会产生一个和原文件同名,以".rej"为后缀的差异文件。当知道 -b 时,会产生一个和原文件同名,以".orig"为后缀的备份文件。
常使用的 patch 参数:
-p 指定目录级别(从路径全称中除去几层目录),如果补丁文件包含路径名称 /curds/whey/src/blurfl/blurfl.c,那么:-p 0 使用完整路径名 -p 1 除去前导斜杠,留下 curds/whey/src/blurfl/blurfl.c。-p 4 除去前导斜杠和前三个目录,留下 blurfl/blurfl.c。
-d Directory 打补丁前,更改当前目录到指定目录
-i PatchFile 从指定文件,而不是从标准输入中读取补丁信息
-R 逆向补丁,这个选项在防止打错补丁很有用处
注意:
1、要打补丁的文件必须是未做任何修改的(这个可以打开补丁文件看一下删除的文件的日期是否和我们要打补丁的文件一样就可以了)。之前就是因为修改了厂商给的源码所以打补丁的时间打不进去,会出错,后来找资料才明白不能改打补丁前的文件。
2、还有一个就是有的补丁要一个一个的打,那是补丁做成这样的,一般厂商给说明是否需要一个一个的打,还直接打最后一个版本的就OK了,但认为一个一个的打的补丁要严谨些,因为它的每一个补丁表示了一次功能性的修改,这样每次都可以验证补丁的正确性了。
示例
a -- 制作补丁
命令:diff -urN linux-3.4.2 linux-3.4.2-my > linux-3.4.2-my.patch
说明:当前路径为:./ 。
该路径(./ )下有 linux-3.4.2 目录,其是linux-3.4.2的源码压缩包解压所得(linux-3.4.2源码未做任何修改的)。
该路径(./ )下有 linux-3.4.2-my 目录,其是由linux-3.4.2的源码修改后,符合开发板正常使用的源码(根据linux-3.4.2源码修改后的)。
生成 linux-3.4.2-my.patch 补丁文件。
b -- 打补丁
命令:patch -p1 < ../linux-3.4.2-my.patch
说明:当前路径为:./linux-3.4.2,进入到未做任何修改的linux-3.4.2的目录下执行patch命令。
diff(differential)
功能说明:比较文件的差异。
语法:diff [-abBcdefHilnNpPqrstTuvwy][-<行数>;][-C <行数>;][-D <巨集名称>;][-I <字符或字符串>;][-S <文件>;][-W <宽度>;][-x <文件或目录>;][-X <文件>;][--help][--left-column][--suppress-common-line][文件或目录1][文件或目录2]
补充说明:diff以逐行的方式,比较文本文件的异同处。所是指定要比较目录,则diff会比较目录中相同文件名的文件,但不会比较其中子目录。
参数:
-<行数>; 指定要显示多少行的文本。此参数必须与-c或-u参数一并使用。
-a或--text diff预设只会逐行比较文本文件。
-b或--ignore-space-change 不检查空格字符的不同。
-B或--ignore-blank-lines 不检查空白行。
-c 显示全部内文,并标出不同之处。
-C<行数>;或--context<行数>; 与执行"-c-<行数>;"指令相同。
-d或--minimal 使用不同的演算法,以较小的单位来做比较。
-D<巨集名称>;或ifdef<巨集名称>; 此参数的输出格式可用于前置处理器巨集。
-e或--ed 此参数的输出格式可用于ed的script文件。
-f或-forward-ed 输出的格式类似ed的script文件,但按照原来文件的顺序来显示不同处。
-H或--speed-large-files 比较大文件时,可加快速度。
-l<字符或字符串>;或--ignore-matching-lines<字符或字符串>; 若两个文件在某几行有所不同,而这几行同时都包含了选项中指定的字符或字符串,则不显示这两个文件的差异。
-i或--ignore-case 不检查大小写的不同。
-l或--paginate 将结果交由pr程序来分页。
-n或--rcs 将比较结果以RCS的格式来显示。
-N或--new-file 在比较目录时,若文件A仅出现在某个目录中,预设会显示:
Only in目录:文件A若使用-N参数,则diff会将文件A与一个空白的文件比较。
-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=<列数>; 以合并的方式来显示文件内容的不同。
-v或--version 显示版本信息。
-w或--ignore-all-space 忽略全部的空格字符。
-W<宽度>;或--width<宽度>; 在使用-y参数时,指定栏宽。
-x<文件名或目录>;或--exclude<文件名或目录>; 不比较选项中所指定的文件或目录。
-X<文件>;或--exclude-from<文件>; 您可以将文件或目录类型存成文本文件,然后在=<文件>;中指定此文本文件。
-y或--side-by-side 以并列的方式显示文件的异同之处。
--help 显示帮助。
--left-column 在使用-y参数时,若两个文件某一行内容相同,则仅在左侧的栏位显示该行内容。
--suppress-common-lines 在使用-y参数时,仅显示不同之处。
patch(打补丁)命令使用详解
功能说明:修补文件。
语法: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 详细显示指令的执行过程。
接下来将会对diff与patch的具体用法做比较深入的分析
两个文件夹比较:diff -urNa dir1 dir2 > file.diff
diff的输出格式分为传统格式和统一格式
1)diff的传统格式输出
############################################
cat before.txt
输出:
This is a line to be deleted
This is a line that will be changed
This is a line that will be unchanged
cat after.txt
输出:
This is a line that has been changed
This is a line that will be unchanged
This is a line that has been added
############################################
diff before.txt after.txt
输出:
1,2c1
< This is a line to be deleted
< This is a line that will be changed
---
> This is a line that has been changed
3a3
> This is a line that has been added
############################################
注释:
传统格式的输出
1,2c1是指替换第1个文件的第1,2行到第2个文件的第2行,这里的1,2是指第1个文件的第1,2行,c是替换的意思,最后的1是第2个文件的第1行
<号是指第1个文件更改或删除的行
---号是分割两个文件
>号是第2个文件中增加或删除的行
3a3是指将第2个文件的第3行插入到第一个文件的第3行
也就是说第1个文件的:
< This is a line to be deleted
< This is a line that will be changed
被替换成第2个文件的:
> This is a line that has been changed
由于第1个文件的第3行和第2个文件的第2行一致,所以不做修改.
由于第2个文件的第3行是第1个文件所不具有的,所以在第1个文件的最后一行增加:
> This is a line that has been added
2)patch命令的应用
用diff的传统格式输出:
#################################
diff before.txt after.txt >mypatch.txt
#################################
用patch修补before.txt文件,使before.txt和after.txt一致.
#################################
cat mypatch.txt |patch before.txt
输出:
patching file before.txt
#################################
比较两个文件,现在是一致的了.
#################################
cmp before.txt after.txt
#################################
用patch命令恢复before.txt.
#################################
patch -R before.txt <mypatch.txt
输出:
patching file before.txt
#################################
注:-R标记告诉patch在反向上应用区别或者撤销patch.
再比较两个文件,现在不一致了.
#################################
cmp before.txt after.txt
输出:
before.txt after.txt differ: byte 17, line 1
#################################
3)diff的统一格式输出
#################################
diff -u before.txt after.txt |tee mypatch.diff
输出:
--- before.txt 2009-06-20 05:21:49.000000000 +0800
+++ after.txt 2009-06-20 04:03:16.000000000 +0800
@@ -1,3 +1,3 @@
-This is a line to be deleted
-This is a line that will be changed
+This is a line that has been changed
This is a line that will be unchanged
+This is a line that has been added
#################################
注释:
diff -u选项是统一格式输出.
--- before.txt 2009-06-20 05:21:49.000000000 +0800
--- before.txt是指旧文件
+++ after.txt 2009-06-20 04:03:16.000000000 +0800
+++ after.txt是指新文件.
@@ -1,3 +1,3 @@
@@ -1,3是指第1个文件一共有3行,+1,3 @@是指第2个文件一共有3行.
-This is a line to be deleted
-This is a line that will be changed
是被删除的行
+This is a line that has been changed
是增加的行
This is a line that will be unchanged
没有-号和+号是指该行不变,因为after.txt和before.txt都有这行.
+This is a line that has been added
是增加的行
diff的统一格式比较与输出是按顺序进行的.
4)diff命令在目录中的应用
新建old和new目录,old目录包含了初始内容,new目录包含文件的最新版本.
##########################################
mkdir old new
echo "This is one. It's unchanged." | tee old/one new/one
echo "This is two. It will change." > old/two
echo "This is two. It changed.">new/two
echo "This is three. It's new" > new/three
##########################################
创建修补文件
##########################################
diff -Nur old/ new/ >mypatch.diff
##########################################
注:-r选项按照文件目录递归创建修补文件.
-u还是统一模式
-N是指当diff遇到一个只存在于两个树中的一个树中的文件时,默认情况下跳过文件并且打印一个警告到stderr.
这个行为可以通过-N选项来更改,这也导致了diff认为丢失的文件实际上是存在的,但它是空的.采用这种方式,
一个修补文件可以包括已经创建的文件.然后应用修补程序创建新的文件.
##########################################
more mypatch.diff
输出:
diff -Nur old/three new/three
--- old/three 1970-01-01 08:00:00.000000000 +0800
+++ new/three 2009-06-20 06:55:34.000000000 +0800
@@ -0,0 +1 @@
+This is three. It's new
diff -Nur old/two new/two
--- old/two 2009-06-20 06:55:08.000000000 +0800
+++ new/two 2009-06-20 06:55:21.000000000 +0800
@@ -1 +1 @@
-This is two. It will change.
+This is two. It changed.
##########################################
注释:
diff -Nur old/three new/three是指下面比较old/three new/three两个文件.
因为没有old/three文件,所以在old/three中增加+This is three. It's new
diff -Nur old/two new/two是指下面比较old/two new/two两个文件
因为old/two与new/two的第3行不一致,所以删除This is two. It will change.增加This is two. It changed.
打补丁到old目录,新建old/three以及更改old/two
##########################################
patch --dir old< mypatch.diff
ls -l old/
输出:
one three two
##########################################
恢复old目录的内容,包括删除old/three,以及恢复old/two文件
##########################################
patch --dir old -R <mypatch.diff
输出:
ls -l old/
one two
##########################################
5)检查和合并更改
用vim突出显示单个字符的更改来表示区别.
##########################################
vim -d after.txt before.txt
##########################################
用gui工具gvimdiff来显示两个文件.
##########################################
gvimdiff after.txt before.txt
##########################################
新建文件orig.c
##########################################
vi orig.c
void foo(void)
{
printf("This will be changed by me. /n");
printf("This will be unchanged,/n");
printf("This will be changed by you./n");
}
##########################################
复制文件orig.c到me.c,更改第4行为printf("This was changed by me. /n");
##########################################
vi me.c
void foo(void)
{
printf("This was changed by me. /n");
printf("This will be unchanged,/n");
printf("This will be changed by you./n");
}
##########################################
复制文件orig.c到you.c,更改第7行为printf("This was changed by you./n");
##########################################
vi you.c
void foo(void)
{
printf("This will be changed by me. /n");
printf("This will be unchanged,/n");
printf("This was changed by you./n");
}
##########################################
版本工具如cvs,subversion使用GNU合并工具称为diff3.
##########################################
diff3 me.c orig.c you.c
输出:
====1
1:3c
printf("This was changed by me. /n");
2:3c
3:3c
printf("This will be changed by me. /n");
====3
1:7c
2:7c
printf("This will be changed by you./n");
3:7c
printf("This was changed by you./n");
注:
在没有参数的情况下,diff3产生的输出说明了那行更改.
====1和====3指明造成同原始文件不同的是哪一个修改文件.
编号方式基于参数序列.
也就是第1个文件和第3个文件与原文件不同.
1:3c
printf("This was changed by me. /n");
3:3c
printf("This will be changed by me. /n");
1:3c表示第1个文件的第3行与3:3c表示的第3个文件的第3行不同.
为什么不显示与原文件的比较呢。因为第3个文件的第3行与源文件(第2个文件)相同.所以与哪个文件比较无所谓了.
2:7c
printf("This will be changed by you./n");
3:7c
printf("This was changed by you./n");
2:7c表示第2个文件的第7行与3:7c表示的第3个文件的第7行不同.
diff3会试图为我们进行合并.合并是在源文件的基础上,依据两个新文件进行修改
源文件是第二个文件,第一个文件和第三个文件可以互换,但他们必须有共同的祖先,就是第二个文件.
#######################################
diff3 -m me.c orig.c you.c |cat -n
输出:
1 void foo(void)
2 {
3 printf("This was changed by me. /n");
4
5 printf("This will be unchanged,/n");
6
7 printf("This was changed by you./n");
8 }
########################################
为了测试更复杂的环境,新建一个文件orig.c.1
内容如下:
########################################
vi orig.c.1
void foo(void)
{
printf("This will be changed by both of us./n");
}
########################################
用diff3 -m再次比较输出,如下:
########################################
diff3 -m me.c orig.c.1 you.c
void foo(void)
{
<<<<<<< me.c
printf("This was changed by me. /n");
printf("This will be unchanged,/n");
printf("This will be changed by you./n");
||||||| orig.c.1
printf("This will be changed by both of us./n");
=======
printf("This will be changed by me. /n");
printf("This will be unchanged,/n");
printf("This was changed by you./n");
>>>>>>> you.c
}
########################################
注释:以上的格式,同cvs update,需要人工合并文件的格式是一致的。
diff实用程序带上-u(unified output format,统一输出格式)选项后,执行结果将首先说明要比较的两个文件,其中一个用正号(+)表示,另一个用负号(-)表示。如图3-8所示,负号代表文件color.1,正号代表文件color.2。
命令diff -u将具有多行的较长文件分成几块。每块前面一行的开始和结束都用符号“@@”标识,其中的数字表明了块中每个文件的起始行编号和行数,数字–1和6表明该块从文件color.1(由负号指明)的第1行到第6行,数字+1和5表明该块包括从color.2的第1行到第5行。
$ diff -u colors.1 colors.2
--- colors.1 2012-04-05 10:12:12.322528610 -0700
+++ colors.2 2012-04-05 10:12:18.420531033 -0700
@@ -1,6 +1,5 @@
red
+blue
green
yellow
-pink
-purple
orange
diff在统一输出格式下的比较结果
在这些头部信息之后,命令diff -u显示了几行文本信息,有的行始于正号,有的行始于负号,有的行正负号都没有(起始于空格)。带正号的行表明其仅出现在正号代表的文件内,带负号的行表明其仅出现在负号代表的文件内,正负号都没有的行表示其出现在两个文件的相同位置。
patch制作及打patch
1,如何制作补丁patch文件
patch文件也叫补丁,就是一个文本文档,这个文档包含了在两个不同版本的源代码树之间的变化。补丁是通过diff应用程序来创建的。为了正确地打上一个补丁,你需要知道这个补丁是从哪个基础版本产生出来的以及这个补丁将要把目前的源代码树变化到什么新的版本。这些信息或者会出现在补丁文件的原数据中,或者可能从文件名中推断出来。
diff 命令的用法
1、"-u":表示在比较结果中输出上下文中一些相同的行,这有利于人工定位
2、"-r":表示递归比较各个子目录下的文件
3、"-N":将不存在的文件当作空文件
4、"-w":忽略对空格的比较
5、"-B":忽略对空行的比较
6、 -a或--text:预设只会逐行比较文本文件;
比如基于kernel内核做了修改,修改lcd 代码,修改前的内容放在文件夹kernel下,修改后的内容放在文件夹kernel_new下,那么制作patch文件的命令为:
~/sourcecode/$diff -Naur kernel/ kernel_new/ >lcd.patch
2,怎样打补丁patch和卸载补丁patch
可以使用patch程序来打一个补丁。patch程序读取一个diff(或者patch)文件,然后把文件中描述的变化内容应用到代码树上。Linux内核中的补丁是相对于保存内核源代码目录的父目录而生成的。这就意味着:patch文件中的文件路径包含了它所基于的内核源文件目录的名字(或者像是"a/"和"b/"之类的其它名字)。
由于这很可能和你本地机器上的内核源代码目录的名字不匹配。你应该切换到你的内核源代码目录,并且在打补丁的时候去掉patch中文件名字路径的第一个分量(patch命令的-p1参数可以完成这个任务)。为了卸载掉一个以前已经打上的补丁,使用-R参数来打补丁。于是,如果你使用如下的命令来打补丁:
patch -p1
那么你可以像下面这样来卸载掉这个补丁:
patch -R -p1
例如其他人下载到上面提供的patch文件后,只需在标准的kernel内核目录里执行
~/sourcecode/kernel/$patch -p1<../zwx-lcd.patch
这里假设zwx-lcd.patch和kernel文件夹是在同一目录下,且上述命令 在kernel文件夹内执行
如果在/sourcecode目录下面执行命令
~/sourcecode/$patch -p0<../zwx-lcd.patch
patch,是打补丁的命令,有很多用法,详见帮助#man patch。
-p参数决定了是否使用读出的源文件名的前缀目录信息,不提供-p参数,则忽略所有目录信息,
patch -p0 (“p"指的是路径,后面的数字表示去掉路径的第几部分。0,表示不去掉,为全路径)
patch -p1 (“p"后面的数字1,表示去掉前第一个路径,第一个"/"以前的目录,依此类推。
如/usr/src/linux-2.6.11/Makefile这样的文件名,在提供-p3参数时将使用linux-2.6.11/Makefile作为所要patch的文件。
对于刚才举的Linux内核源码LCD升级包的例子,假定源码目录位于/home/freeoa/sourcecode/kernel中,则在当前目录为/home/freeoa/sourcecode/时使用"patch -p0<../zwx-lcd.patch"可以工作,在当前目录为/home/freeoa/sourcecode/kernel时,使用"patch -p1<../zwx-lcd.patch"也可以正常工作。
如果patch文件里面描述的第一级目录和你自己的第一级目录名字不一样,要将第一级的目录去掉,这个方法就派上用场了。比如如果你拿到的patch描述的目录和你的不一样,patch第一行描述的目录信息
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
但是你的目录既不是a,也不是b,那么你就要将目录的第一层去掉,到你的kernel的路径下面打patch用-p1参数
diff可以完成比较功能,生成补丁文件。
格式:diff [option] oldfile newfile
常用的option选项有:
-r 对目录进行递归处理
-u 输出统一格式,diff有"传统"和"统一"两种格式,现在一般使用"统一"格式,比较而言,统一格式生成的文件大,但包含了更多的信息,有利于阅读与定位
-N 补丁中包含整个新文件
-a 补丁中包含二进制文件
缺省时,diff向标准输出打印,所以一般都重定向到文件并以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 命令失败或拒绝接受补丁时,会产生一个和原文件同名,以".rej"为后缀的差异文件。当知道 -b 时,会产生一个和原文件同名,以".orig"为后缀的备份文件。
常使用的 patch 参数:
-p 指定目录级别(从路径全称中除去几层目录),如果补丁文件包含路径名称 /curds/whey/src/blurfl/blurfl.c,那么:-p 0 使用完整路径名 -p 1 除去前导斜杠,留下 curds/whey/src/blurfl/blurfl.c。-p 4 除去前导斜杠和前三个目录,留下 blurfl/blurfl.c。
-d Directory 打补丁前,更改当前目录到指定目录
-i PatchFile 从指定文件,而不是从标准输入中读取补丁信息
-R 逆向补丁,这个选项在防止打错补丁很有用处
注意:
1、要打补丁的文件必须是未做任何修改的(这个可以打开补丁文件看一下删除的文件的日期是否和我们要打补丁的文件一样就可以了)。之前就是因为修改了厂商给的源码所以打补丁的时间打不进去,会出错,后来找资料才明白不能改打补丁前的文件。
2、还有一个就是有的补丁要一个一个的打,那是补丁做成这样的,一般厂商给说明是否需要一个一个的打,还直接打最后一个版本的就OK了,但认为一个一个的打的补丁要严谨些,因为它的每一个补丁表示了一次功能性的修改,这样每次都可以验证补丁的正确性了。
示例
a -- 制作补丁
命令:diff -urN linux-3.4.2 linux-3.4.2-my > linux-3.4.2-my.patch
说明:当前路径为:./ 。
该路径(./ )下有 linux-3.4.2 目录,其是linux-3.4.2的源码压缩包解压所得(linux-3.4.2源码未做任何修改的)。
该路径(./ )下有 linux-3.4.2-my 目录,其是由linux-3.4.2的源码修改后,符合开发板正常使用的源码(根据linux-3.4.2源码修改后的)。
生成 linux-3.4.2-my.patch 补丁文件。
b -- 打补丁
命令:patch -p1 < ../linux-3.4.2-my.patch
说明:当前路径为:./linux-3.4.2,进入到未做任何修改的linux-3.4.2的目录下执行patch命令。