`
kongweile
  • 浏览: 521463 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

【linux】利用patch和diff命令制作文件补丁

 
阅读更多

因为在 u-boot 移植过程中,有几处通用文件要修改,如果每次都要手动修改就太麻烦了。制作补丁可以解决这个问题。

学习资料的收集比较简单,方法一类似于这种初级问题网上资料非常丰富, google 或者 baidu 搜索一下,然后选择有价值的资料,方法二是阅读 man 在线文档。完成收集工作,当然最终要在自己的 Linux 上作实验,比较总结,消化吸收为自己的东西。要除去这么一种错误思想:一定要学全。要知道,一次学全是不可能的,只能先学习最为常用的,在以后不断实践的过程中逐步的丰富,最终达到比较高的水平。把握的原则是:日有所学,学以致用,用以促学。

首先介绍一下 diff  patch 。在这里不会把 man 在线文档上所有的选项都介绍一下,那样也没有必要。在 99%的时间里,我们只会用到几个选项。所以必须学会这几个选项。

1  diff

--------------------

NAME

       diff - find differences between two files

SYNOPSIS

       diff [options] from-file to-file

--------------------

简单的说, diff 的功能就是用来比较两个文件的不同,然后记录下来,也就是所谓的 diff 补丁。语法格式:diff 【选项】 源文件(夹) 目的文件(夹) ,就是要给源文件(夹) 打个补丁,使之变成目的文件(夹) ,术语也就是“升级”。下面介绍三个最为常用选项:

-r 是一个递归选项,设置了这个选项, diff 会将两个不同版本源代码目录中的所有对应文件全部都进行一次比较,包括子目录文件。

-N 选项确保补丁文件将正确地处理已经创建或删除文件的情况。

-u 选项以统一格式创建补丁文件,这种格式比缺省格式更紧凑些。

2  patch

------------------

NAME

       patch - apply a diff file to an original

SYNOPSIS

       patch [options] [originalfile [patchfile]]

       but usually just

       patch -pnum <patchfile>

------------------

简单的说, patch 就是利用 diff 制作的补丁来实现源文件(夹) 和目的文件(夹) 的转换。这样说就意味着你可以有源文件(夹) ―― > 目的文件(夹) ,也可以目的文件(夹) ―― > 源文件(夹)。 下面介绍几个最常用选项:

-p0 选项要从当前目录查找目的文件(夹)

-p1 选项 要忽略掉第一层目录,从当前目录开始查找。

************************************************************

 

在这里以实例说明:

--- old/modules/pcitable       Mon Sep 27 11:03:56 1999

+++ new/modules/pcitable       Tue Dec 19 20:05:41 2000

    如果使用参数-p0,那就表示从当前目录找一个叫做old的文件夹,在它下面寻找modules下的pcitable文件来执行patch操作。

    如果使用参数-p1,那就表示忽略第一层目录(即不管old),从当前目录寻找modules的文件夹,在它下面找pcitable。这样的前提是当前目 录必须为modules所在的目录。而diff补丁文件则可以在任意位置,只要指明了diff补丁文件的路径就可以了。当然,可以用相对路径,也可以用绝 对路径。不过我一般习惯用相对路径。

************************************************************

 

-E  选项说明如果发现了空文件,那么就删除它

-R  选项说明在补丁文件中的    文件和    文件现在要调换过来了(实际上就是给新版本打补丁,让它变成老版本)

下面结合具体实例来分析和解决,分为两种类型:为单个文件打补丁和为文件夹内的多个文件打补丁。

环境:在 RedHat 9.0 下面以 armlinux 用户登陆。

目录树如下:

|-- bootloader

|-- debug

|-- images

|-- kernel

|-- program

|-- rootfiles

|-- software

|-- source

|-- sysapps

|-- tmp

`-- tools

下面在 program 文件夹下面建立 patch 文件夹作为实验用,然后进入 patch 文件夹。

一、为单个文件进行补丁操作

1 、建立测试文件 test0  test1

[armlinux@lqm patch]$ cat  >>test0<<EOF

> 111111

> 111111

> 111111

> EOF

[armlinux@lqm patch]$ more test0

111111

111111

111111

[armlinux@lqm patch]$ cat >>test1<<EOF

> 222222

> 111111

> 222222

> 111111

> EOF

[armlinux@lqm patch]$ more test1

222222

111111

222222

111111

2 、使用 diff 创建补丁 test1.patch

[armlinux@lqm patch]$ diff -uN test0 test1 > test1.patch

【注:因为单个文件,所以不需要 -r 选项。选项顺序没有关系,即可以是 -uN ,也可以是 -Nu 。】

[armlinux@lqm patch]$ ls

test0  test1  test1.patch

[armlinux@lqm patch]$ more test1.patch

************************************************************

patch 文件的结构

补丁头

补丁头是分别由 ---/+++ 开头的两行,用来表示要打补丁的文件。 --- 开头表示旧文件, +++ 开头表示新文件。

一个补丁文件中的多个补丁

一个补丁文件中可能包含以 ---/+++ 开头的很多节,每一节用来打一个补丁。所以在一个补丁文件中可以包含好多个补丁。

块是补丁中要修改的地方。它通常由一部分不用修改的东西开始和结束。他们只是用来表示要修改的位置。他们通常以 @@ 开始,结束于另一个块的开始或者一个新的补丁头。

块的缩进

块会缩进一列,而这一列是用来表示这一行是要增加还是要删除的。

块的第一列

+ 号表示这一行是要加上的。

- 号表示这一行是要删除的。

没有加号也没有减号表示这里只是引用的而不需要修改。

************************************************************

***diff 命令会在补丁文件中记录这两个文件的首次创建时间,如下 ***

--- test0       2006-08-18 09:12:01.000000000 +0800

+++ test1       2006-08-18 09:13:09.000000000 +0800

@@ -1,3 +1,4 @@

+222222

  111111

-111111

+222222

  111111

[armlinux@lqm patch]$ patch -p0 < test1.patch

patching file test0

[armlinux@lqm patch]$ ls

test0  test1  test1.patch

[armlinux@lqm patch]$ cat test0

222222

111111

222222

111111

3、可以去除补丁,恢复旧版本

[armlinux@lqm patch]$ patch -RE -p0 < test1.patch

patching file test0

[armlinux@lqm patch]$ ls

test0  test1  test1.patch

[armlinux@lqm patch]$ cat test0

111111

111111

111111

二、为多个文件进行补丁操作

1 、创建测试文件夹

[armlinux@lqm patch]$ mkdir prj0

[armlinux@lqm patch]$ cp test0 prj0

[armlinux@lqm patch]$ ls

prj0  test0  test1  test1.patch

[armlinux@lqm patch]$ cd prj0/

[armlinux@lqm prj0]$ ls

test0

[armlinux@lqm prj0]$ cat >>prj0name<<EOF

> --------

> prj0/prj0name

> --------

> EOF

[armlinux@lqm prj0]$ ls

prj0name  test0

[armlinux@lqm prj0]$ cat prj0name

--------

prj0/prj0name

--------

[armlinux@lqm prj0]$ cd ..

[armlinux@lqm patch]$ mkdir prj1

[armlinux@lqm patch]$ cp test1 prj1

[armlinux@lqm patch]$ cd prj1

[armlinux@lqm prj1]$ cat >>prj1name<<EOF

> ---------

> prj1/prj1name

> ---------

> EOF

[armlinux@lqm prj1]$ cat prj1name

---------

prj1/prj1name

---------

[armlinux@lqm prj1]$ cd ..

2 、创建补丁

[armlinux@lqm patch]$ diff -uNr prj0 prj1 > prj1.patch

[armlinux@lqm patch]$ more prj1.patch

 

diff -uNr prj0/prj0name prj1/prj0name

--- prj0/prj0name       2006-08-18 09:25:11.000000000 +0800

+++ prj1/prj0name       1970-01-01 08:00:00.000000000 +0800

@@ -1,3 +0,0 @@

---------

-prj0/prj0name

---------

diff -uNr prj0/prj1name prj1/prj1name

--- prj0/prj1name       1970-01-01 08:00:00.000000000 +0800

+++ prj1/prj1name       2006-08-18 09:26:36.000000000 +0800

@@ -0,0 +1,3 @@

+---------

+prj1/prj1name

+---------

diff -uNr prj0/test0 prj1/test0

--- prj0/test0  2006-08-18 09:23:53.000000000 +0800

+++ prj1/test0  1970-01-01 08:00:00.000000000 +0800

@@ -1,3 +0,0 @@

-111111

-111111

-111111

diff -uNr prj0/test1 prj1/test1

--- prj0/test1  1970-01-01 08:00:00.000000000 +0800

+++ prj1/test1  2006-08-18 09:26:00.000000000 +0800

@@ -0,0 +1,4 @@

+222222

+111111

+222222

+111111

 

[armlinux@lqm patch]$ ls

prj0  prj1  prj1.patch  test0  test1  test1.patch

[armlinux@lqm patch]$ cp prj1.patch ./prj0

[armlinux@lqm patch]$ cd prj0

[armlinux@lqm prj0]$ patch -p1 < prj1.patch

patching file prj0name

patching file prj1name

patching file test0

patching file test1

[armlinux@lqm prj0]$ ls

prj1name  prj1.patch  test1

[armlinux@lqm prj0]$ patch -R -p1 < prj1.patch

patching file prj0name

patching file prj1name

patching file test0

patching file test1

[armlinux@lqm prj0]$ ls

prj0name  prj1.patch  test0

-------------------

 

总结一下:

单个文件

diff –uN   from-file   to-file   >to-file.patch

patch –p0 < to-file.patch

patch –RE –p0 < to-file.patch

多个文件

diff –uNr   from-docu   to-docu  >to-docu.patch

patch –p1 < to-docu.patch

patch –R –p1 <to-docu.patch

-------------------

 

三、应用

为内核打补丁。前面在创建交叉编译工具链时,其中有一步就是为内核打补丁。当时还不是特别了解,现在很清晰了。参考前面的文章《基于 ARM+Linux 嵌入式开发的开发工具链的建立》。

1 、首先是解压,因为发布的补丁文件都是使用 gzip 压缩的。

$gunzip ../setup-dir/ patch-2.4.21-rmk1.gz

2 、然后进入你的内核源代码目录

$cd linux-2.4.21

3 、打补丁

$patch –p1 < ../../setup-dir/patch-2.4.21-rmk1

       打完补丁后,需要检查一下有没有拒绝执行的文件,即检查.rej文件的存在。使用命令:

       $find  .  -name  *.rej

       如果发现,会将其输出到标准输出终端,默认屏幕。当然,你也可以采用重定向,输出到指定文件,比如reject。

       $fine  .  -name  *.rej  >reject

       然后可以查看reject的内容了。

分享到:
评论

相关推荐

    Linux下patch打补丁命令实例详解.txt

    在Linux系统中,`patch`命令是一个非常重要的工具,用于将源代码的差异(通常由`diff`工具生成)应用到现有的源代码库上,从而实现对软件的更新或修复。本文将深入探讨`patch`命令的用法及其在实际场景中的应用实例...

    linux下patch安装包

    - `patch-2.6.tar.gz`和`patches3.0.tgz`可能分别包含针对Linux内核2.6和3.0的补丁文件,每个`.diff`文件对应源代码的一个或多个更改。 3. **解压和应用补丁**: - 对于`patch-2.6.tar.gz`和`patches3.0.tgz`,...

    Linux下patch的制作和应用

    `patch` 命令用于将 `diff` 生成的补丁文件应用到原始文件上,实现源文件向目标文件的转换。 #### 常用选项 - `-p0`:从当前目录查找目标文件。 - `-p1`:忽略第一层目录,从当前目录开始查找目标文件。 - `-E`:...

    linux 打补丁patch 详解

    Linux 打补丁 Patch 详解 ...当用 patch 命令来打一个补丁的时候,它试图以不同的方法来验证这个文件的完整性。检查这个文件是一个有效的 patch 文件并且检查这些被改变周围的代码是不是和提供的上下文相匹配。

    linux diff命令详解

    如果 `file2` 丢失了,但拥有 `file1` 和补丁文件 `file3`,那么可以使用 `patch` 命令将 `file1` 更新为 `file2` 的状态。这里的 `-p0` 参数表示补丁路径前缀的深度为0,即补丁应用于当前目录。 #### 五、深入...

    Linux下Patch的应用和制作方法

    因为在u-boot移植过程中,有几处通用文件要修改,如果每次都要手动修改就太麻烦了。制作补丁可以解决这个问题。本文首介绍一下diff和patch。然后介绍了制作Patch为单个文件和多个文件进行补丁操作的方法。

    Linux入门培训教程linux命令大全之diff命令详解借鉴.pdf

    Diff 程序的输出被称为补丁 (patch),因为 Linux 系统中还有一个 patch 程序,可以根据 diff 的输出将 a.c 的文件内容更新为 b.c 。 Diff 命令的基本格式为:diff [参数] [文件 1 或目录 1] [文件 2 或目录 2]。...

    Linux命令学习手册-patch命令

    `patch` 命令是Linux系统中的一个非常实用且强大的工具,主要用于应用补丁文件来更新现有的文件或目录。补丁文件通常是由`diff` 命令创建的,包含了源文件与目标文件之间的差异。通过`patch` 命令可以将这些差异应用...

    Linux下Patch的应用和制作方法介绍.docx

    对于文件夹内的多个文件打补丁,只需确保`diff`命令使用了`-r`选项,`patch`命令会自动处理所有包含在补丁文件中的更改。 在Red Hat 9.0环境下,例如在`program`文件夹内有多个文件需要打补丁,首先要生成补丁,...

    如何使用diff和patch

     diff A B &gt;C ,一般A是原始文件,B是修改后的文件,C称为A的补丁文件。  patch A C 就能得到B, 这一步叫做对A打上了B的名字为C的补丁。  patch -R B C 就可以重新还原到A了。  2) 内核补丁  生成  diff -uNr ...

    Linux中patch文件的使用.doc

    在Linux系统中,`patch`命令和`diff`工具是非常重要的文件对比与合并工具。它们主要用于软件开发过程中的版本管理和更新,尤其在开源社区中非常常见。通过这些工具,开发者可以轻松地在不同版本之间进行代码比较,并...

    diff命令 文件比较工具 文本比较工具 cygwin中的文本比较工具

    在软件开发中,`diff`常常与版本控制系统(如Git)结合使用,生成所谓的“补丁”文件(`.patch`),这是一个记录了文件变化的文本文件,可以应用到其他副本上,以同步修改。这在代码审查和协作开发中非常关键。 总...

    armboot-org2mini2440.diff patch补丁包

    补丁方法:将原始的armboot程序包armboot-1.1.0.tgz 解开后,将armboot-org2mini2440.diff文件放到和armboot-1.1.0的同级目录上,不要拷贝到 armboot-1.1.0 目录里面, 进到 armboot-1.1.0 执行如下的patch命令即可...

    Linux操作命令九.doc

    本文将详细介绍 Linux 操作系统中六个重要命令:comm 命令、diff 命令、patch 命令、df 命令、du 命令和 time 命令。这些命令都是 Linux 系统中不可或缺的一部分,掌握这些命令对日常的系统维护和管理具有重要意义。...

    node命令行生成补丁文件合并补丁生成新的文件

    通常,这样的工具会使用类似`diff`和`patch`的API,这些都是Unix/Linux系统中用于比较和应用补丁的标准工具。在Node.js中,有一些流行的库,如`node-diff3`、`node-patch`或`npm install patch-package`等,它们实现...

    linux patch 命令小结(收藏)

    然后在xxx目录下用diff命令,建立一个补丁文件xxx.patch,在xx目录下建立一个补丁文件xx.patch,在x目录下建立一个补丁文件x.patch。然后在这三个目录下实验。 开始实验:建立实验目录 [King@Fedora ~]$

    Linux初学者Patch使用指南

    通常情况下,你需要将patch文件放在需要打补丁的目录下,并在这个目录中运行命令。 2. **撤销Patch:** ``` patch -R [patchfile] ``` `-R`选项用于撤销已应用的patch。 #### 三、Patch的实际应用场景 **...

    系统运维之linux系统打补丁

    如果没有联网或者有特殊的情况也可以使用 diff 和 patch 命令来打补丁。 生成补丁 --------- 补丁文件是使用 diff 命令生成的,其命令格式如下: diff -uNr oldfile newfile &gt; patch_file.patch 其中,diff 命令...

    为Linux内核打补丁

    - **处理压缩文件**:对于压缩的补丁文件,可以使用`zcat`或`bzcat`直接解压并通过标准输入传递给`patch`命令,例如`zcat path/to/patch-x.y.z.gz | patch -p1`。 #### 四、其他有用的`patch`命令参数 - **`-s`...

Global site tag (gtag.js) - Google Analytics