Linux中的Diff和Patch
本文主要记录两个命令的学习情况:diff 和 patch。diff 和 patch 是一对工具,使用这对工具可以获取更新文件与历史文件的差异,并将更新应用到历史文件上。在数学上说,diff就是对两个集合的差运算,patch就是对两个集合的和运算。
简单的例子
使用这个例子来说明如何进行文件的对比和打补丁。
这里有两个文件 original.txt 和 updated.txt,如下:
#include <stdio.h>
function old(){
printf("This is a file\n");
return 0;
}
#include stdio.h
function new(){
printf("This is b file\n");
return 0;
}
执行 diff original.txt updated.txt
的结果为
下面先对结果中出现的一些符号做一些解释。1,4c1
,这个内容输出实际上是给patch看的,表示告诉patch在original.txt文件中的1到4行应当被updated.txt中的内容替换,替换的内容是updated.txt的第1行。这里可能会出现三个字母表示不同的意义,分别是c表示更新、a表示追加、d表示删除。
c表示在original文件中的m,n行的内容将要被updated文件中的内容替换。
a表示追加,这时左边的数字只能是一个数字,而不会是一个范围,表示向original文件中追加右侧数字表示内容。
d表示删除。左侧的数字可能是一个范围,表示要删除的内容,右侧是一个数字,表示如果没有被删除应该出现在updated文件的什么位置。也许有人觉得后边的数字是多余的,保留这个数字是因为补丁可以反向使用。
<
表示patch应当将这个标志后面的内容删除。
>
表示patch应当将这个标志后面的内容添加。
了解了diff的输出结果,该给original文件创建补丁了。补丁实际上就是diff的输出结果,我们可以直接将输出结果保存成文件,也可以使用管道符号做这件事,如下:
diff original.txt updated.txt > mypatch.patch
这时我们就有了一个补丁文件,可以将original文件更新了updated文件了。
patch original.txt -i my patch.patch -o updated-1.txt
这个命令会生成一个新的文件,可以看到这个我们之前的update.txtw文件一模一样。
上下文补丁
观察之前diff给出的结果样式,对于需要替换的位置,仅仅给出了行号,如果文件突然新增了一个空行,补丁应用的时候就会发生问题。另外一种情况,如果将补丁文件应用到了一个错误的源文件上,假如恰好这个文件有同样的行数,那么补丁也可以成功应用。而这都是我们不希望看到的结果。幸好,diff提供了一种不同的结果样式来避免上面的这些问题。
diff -c original.txt updated.txt
比较结果中包含了文件名,这样我们在应用补丁的时候,就不用输入文件名,从而节省了时间,避免了文件名输入错误的可能。文件名后都跟着文件的修改时间。再往下就是15个星号 * 表示后面的内容为文件替换、更新、删除等。*
和-
包含的数字或者数字范围表示行号,!
开始的内容表示需要替换的内容,-
表示需要删除的内容,+
表示需要增加的内容,patch会依据这个上下文关系对文件进行更新。
patch -i mypatch2.patch -o updated.txt
注意,这里如果不指定输出文件的话,源文件就会被更新(这本来就是补丁文件的作用)。通常我们都会对源文件应用补丁,通常需要对多个文件进行处理。
比较多个文件并应用补丁
比较多个文件最简单的办法就是直接在命令后面跟文件夹,例如,如果包含子文件夹,记得加上 -r 参数。
diff originaldirectory updateddirectory
也可以看看上下文比较的结果
RousseaudeMacBook-Pro:diff rousseau$ diff -c original update
diff -c original/function.txt update/function.txt
*** original/function.txt Fri Feb 17 09:41:26 2017
--- update/function.txt Fri Feb 17 09:42:06 2017
***************
*** 1,5 ****
! #includ <stdio.h>
function main(){
return 1;
}
--- 1,8 ----
! #include <stdio.h>
! #include <stdlib.h>
function main(){
+ printf("This is function main\n");
+
return 1;
}
diff -c original/original.txt update/original.txt
*** original/original.txt Fri Feb 17 09:40:29 2017
--- update/original.txt Fri Feb 17 09:40:51 2017
***************
*** 1,9 ****
#include <stdio.h>
! function old(){
! printf("This is a file\n");
return 0;
}
- void 0;
--- 1,8 ----
#include <stdio.h>
! function newd(){
! printf("This is a new file\n");
return 0;
}
下面来看看怎么对多个文件应用补丁,首先生成一个补丁文件,我们还是用上下文的格式。diff -c original update > directory.patch
在一个新的目录下拷贝 original 文件夹和补丁文件,执行 patch -i directory.patch
,此时会提示找不到文件,因为patch会在当前文件夹查找文件(默认情况下patch会将文件名前的所有文件夹去掉)因为此时补丁文件在文件夹外面,所以我们应当告诉patch不要这么做,使用-p
参数。
patch -p0 -i directory.patch
也许有人会问,如果我把补丁文件移动到文件夹中进行打补丁操作不就可以了嘛,注意千万不要这么做。如果文件夹中还有子文件夹,那么patch不会到子文件夹中寻找文件,这样就会对结果产生影响,特别是在不同文件夹中有相同名字的文件的时候。
还原补丁文件的操作
有时候版本需要进行回撤,这时可以使用 -R 参数。
patch -p0 -R -i directory.patch
Unified Format
GNU的diff和patch还提供了一种格式,称为 the unified format。这个格式更加精简,与上下文格式类似。但是不再将源文件和更新文件分开,而是组合在一起。并且没有特殊的替换标志,只有-和+。
diff -u original update
写在最后
对文本文件进行patch操作时,提前备份是一个好习惯,这可以避免你在弄错的情况下,面临一堆无法恢复的文件发愁。
参考资料:
1、Using Diff and patch
2、Diff比较两个文件夹
3、GNU Diff and patch
Linux中的Diff和Patch的更多相关文章
- linux中的diff命令
今天在公司的代码中看到了一个用的不是很多的命令diff,一开始以为不是,后来一查发现还真有这个命令,有关它的详细资料在这个网址中查看[http://blog.chinaunix.net/uid-253 ...
- diff和patch
diff -u:the unified format会将不同的地方放在一起,紧凑易读 . diff original.txt updated.txt c表示在original文件中的m,n行的内容将要 ...
- Linux下diff与patch命令的配合使用
在Linux下,diff与patch命令配合使用可以进行简单的代码维护工作. [A] diff diff命令用于比较文件的差异,可以用于制作patch文件.但此命令参数众多.格式多样,所以在此仅介绍较 ...
- diff和patch配合使用(转载备用)
Linux下diff与patch命令的配合使用 在Linux下,diff与patch命令配合使用可以进行简单的代码维护工作. [A] diffdiff命令用于比较文件的差异,可以用于制作patch文件 ...
- 用Diff和Patch工具维护源码
在Unix系统下,维护源码版本可以使用很多方法,其中最常用的当然是大名鼎鼎的CVS,但实际上,简单的版本维护工作并没有必要使用复杂的CVS等专门的版本维护工具,Unix标配中的diff和patch工具 ...
- Linux中的版本控制---diff和patch命令
一.构造两个用于测试的文件 hello.txt: world.txt: 二.用diff命令比较两个文本文件的差异 对这个两个文本文件执行diff‘命令,并通过输出重定向,将差异保存在diff.txt文 ...
- Linux游(1): diff, patch和quilt (下一个)
Linux游(1): diff, patch和quilt (下一个) 2 quilt 我们自己的项目可以用cvs或svn管理所有代码.但有时我们要使用其它开发人员维护的项目.我们须要改动一些文件.但又 ...
- Linux中正则表达式和字符串的查询、替换(tr/diff/wc/find)
目录 正则表达式 基本正则表达式 扩展正则表达式 grep tr diff du wc find 正则表达式 正则表达式,又称正规表示法.常规表示法( Regular Expression,在代码中常 ...
- diff和patch的使用、patch文件的格式解说
为了弄懂 patch中的 p0 p1 和.orig文件是啥,找到了这篇文章! 来源:http://www.cnblogs.com/super119/archive/2010/12/18/19 ...
随机推荐
- JavaScript术语:shim 和 polyfill
转自:https://www.html.cn/archives/8339 在学习和使用 JavaScript 的时候,我们会经常碰到两个术语:shim 和 polyfill.它们有许多定义和解释,意思 ...
- Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)-A-Single Wildcard Pattern Matching
#include<iostream> #include<algorithm> #include<stdio.h> #include<string.h> ...
- CentOS 6.7下 Samba服务器的搭建与配置(share共享模式)
https://www.linuxidc.com/Linux/2016-12/138220.htm
- js面向对象高级编程
面向对象的组成 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...
- [转帖] cnblog新闻区 “40岁以上的员工,请自觉离开”
“40岁以上的员工,请自觉离开” 投递人 itwriter 发布于 2018-04-29 22:36 评论(9) 有2733人阅读 原文链接 [收藏] « » “准确地说,华为目前要裁掉的.清退的,是 ...
- Angular $cookieStore简单应用
angular.module('cookieStoreExample', ['ngCookies']) .controller('ExampleController', ['$cookieStore' ...
- ionic2/3注册安卓返回
如果使用了 this.app.getRootNav().push()以及this.navCtrl.push(); 则在注册安卓返回键的时候 registerBackButtonAction() ...
- 用java编网页的学习流程,我的一些小心得(初学java到高深运用)
(1)java基础:首先得会写int,String,for循环,数组,**等等(熟练各种基础的关键字,各种java自带的排序,随即等等算法)什么是封装,继承,多态,然后private,public,p ...
- jquery Ajax noConflict()
如果幾個框架都在使用$作為標識符,那麼這個時候可以使用noConflict()處理衝突. 可以直接使用jquery代替簡寫,也可以定義變量,也可以將$賦值給ready函數,函數內部可以使用快捷方式,不 ...
- python之count()函数
# count()统计字符串中特定单词或短语出现次数(n = 3) strs = 'Good! Today is good day! Good job!' n = strs.lower().count ...