diff 与 patch 的使用 | Linux 中国

diff 与 patch 的使用 | Linux 中国
在 Linux 的日常使用中,我们经常需要修改一些配置文件,然而在软件升级以后,经常会面临配置更新后与原配置部分不兼容的问题(当然我们更多的可能是来制作软件升级的补丁)-- Locez

有用的原文链接请访问文末的“

原文链接

”获得可点击的文内链接、全尺寸原图和相关文章。致谢

转载自 | http://locez.com/linux/diff-and-patch/



 作者 | Locez

摘要

在 Linux 的日常使用中,我们经常需要修改一些配置文件,然而在软件升级以后,经常会面临配置更新后与原配置部分不兼容的问题(当然我们更多的可能是来制作软件升级的补丁)。在这种情况下我们通常有两种选择:

? 对比现有配置,手动在新配置文件中改动? 利用 sed、awk 等工具配合改动? 采用 diff 与 patch 制作增量补丁的方式改动

本文主要通过一个升级awesome 配置的例子,对第三种方法进行介绍和讲解。

diff 介绍

diff 是一个文件比较工具,可以逐行比较两个文件的不同,其中它有三种输出方式,分别是 normal, context 以及 unified。区别如下:

? normal 方式为默认输出方式,不需要加任何参数? context 相较于 normal 模式的简单输出,contetx 模式会输出修改过部分的上下文,默认是前后 3 行。使用参数 -c? unified 合并上下文模式则为新的上下文输出模式,同样为前后 3 行,只不过把上下文合并了显示了。使用参数 -u

:本文主要介绍 unified 模式

其他常用参数:

? -r 递归处理目录? -N 将缺失的文件当作空白文件处理

diff 语法与文件格式

  • diff

    [

    options

    ]

    old

    new

  • 先来看一个简单的例子:

  • $

    cat

    test1

  • linux

  • linux

  • linux

  • linux

  • $

    cat

    test2

  • locez

  • linux

  • locez

  • linux

  • 此时输入 diff -urN test1 test2 会输出以下信息:

  • ---

    test1  

    2018

    -

    05

    -

    12

    18

    :

    39

    :

    41.508375114

    +

    0800

  • +++

    test2  

    2018

    -

    05

    -

    12

    18

    :

    41

    :

    00.124031736

    +

    0800

  • @@

    -

    1

    ,

    4

    +

    1

    ,

    4

    @@

  • +

    locez

  • linux

  • -

    linux

  • -

    linux

  • +

    locez

  • linux

  • 先看前面 2 行,这两行为文件的基本信息,--- 开头为改变前的文件,+++ 开头为更新后的文件。

  • ---

    test1  

    2018

    -

    05

    -

    12

    18

    :

    39

    :

    41.508375114

    +

    0800

  • +++

    test2  

    2018

    -

    05

    -

    12

    18

    :

    41

    :

    00.124031736

    +

    0800

  • 第三行为上下文描述块,其中 -1,4 为旧文件的 4 行上下文,+1,4 为新文件的:

  • @@

    -

    1

    ,

    4

    +

    1

    ,

    4

    @@

  • 而具体到块里面的内容,前面有 - 号的则为删除,有 + 号为新增,不带符号则未做改变,仅仅是上下文输出。

    patch 介绍

    patch 是一个可以将 diff 生成的

    补丁

    应用到源文件,生成一个打过补丁版本的文件。语法:

  • patch

    [

    oiption

    ]

    [

    originalfile

    [

    patchfile

    ]]

  • 常用参数:

    ? -i 指定补丁文件? -pNum 在 diff 生成的补丁中,第一二行是文件信息,其中文件名是可以包含路径的,例如 --- /tmp/test1 2018-05-12 18:39:41.508375114 +0800 其中 -p0 代表完整的路径 /tmp/test1,而 -p1 则指 tmp/test1,-pN 依此类推? -E 删除应用补丁后为空文件的文件? -o 输出到一个文件而不是直接覆盖文件

    应用

    awesome 桌面 3.5 与 4.0 之间的升级是不兼容的,所以在升级完 4.0 以后,awesome 桌面部分功能无法使用,因此需要迁移到新配置,接下来则应用 diff 与 patch 实现迁移,当然你也可以单纯使用 diff 找出不同,然后手动修改新配置。

    现在有以下几个文件:

    ? rc.lua.3.5 3.5 版本的默认配置文件,未修改? rc.lua.myconfig 基于 3.5 版本的个人配置文件? rc.lua.4.2 4.2 新默认配置,未修改

    思路为利用 diff 提取出个人配置与 3.5 默认配置文件的增量补丁,然后把补丁应用在 4.2 的文件上实现迁移。

    制作补丁

  • $

    diff

    -

    urN rc

    .

    lua

    .

    3.5

    rc

    .

    lua

    .

    myconfig  

    >

    mypatch

    .

    patch

  • 应用补丁

  • $

    patch

    rc

    .

    lua

    .

    4.2

    -

    i mypatch

    .

    patch

    -

    o rc

    .

    lua

  • patching

    file

    rc

    .

    lua

    (

    read

    from

    rc

    .

    lua

    .

    4.2

    )

  • Hunk

    #

    1

    FAILED at

    38.

  • Hunk

    #

    2

    FAILED at

    55.

  • Hunk

    #

    3

    succeeded at

    101

    with

    fuzz

    1

    (

    offset

    5

    lines

    ).

  • Hunk

    #

    4

    succeeded at

    276

    with

    fuzz

    2

    (

    offset

    29

    lines

    ).

  • 2

    out of

    4

    hunks FAILED

    --

    saving rejects to

    file

    rc

    .

    lua

    .

    rej

  • 显然应用没有完全成功,其中在 38 行以及 55 行应用失败,并记录在 rc.lua.rej 里。

  • $

    cat

    rc

    .

    lua

    .

    rej

  • ---

    rc

    .

    lua

    .

    3.5

     

    2018

    -

    05

    -

    12

    19

    :

    15

    :

    54.922286085

    +

    0800

  • +++

    rc

    .

    lua

    .

    myconfig

    2018

    -

    05

    -

    12

    19

    :

    13

    :

    35.057911463

    +

    0800

  • @@

    -

    38

    ,

    10

    +

    38

    ,

    10

    @@

  • --

    {{{

    Variable

    definitions

  • --

    Themes

    define

    colours

    ,

    icons

    ,

    font

    and

    wallpapers

    .

  • -

    beautiful

    .

    init

    (

    "@AWESOME_THEMES_PATH@/default/theme.lua"

    )

  • +

    beautiful

    .

    init

    (

    "~/.config/awesome/default/theme.lua"

    )

  • --

    This

    is

    used later

    as

    the

    default

    terminal

    and

    editor to run

    .

  • -

    terminal

    =

    "xterm"

  • +

    terminal

    =

    "xfce4-terminal"

  • editor

    =

    os

    .

    getenv

    (

    "EDITOR"

    )

    or

    "nano"

  • editor_cmd

    =

    terminal

    ..

    " -e "

    ..

    editor

  • @@

    -

    55

    ,

    18

    +

    55

    ,

    18

    @@

  • --

    Table

    of layouts to cover

    with

    awful

    .

    layout

    .

    inc

    ,

    order matters

    .

  • local

    layouts

    =

  • {

  • -

       awful

    .

    layout

    .

    suit

    .

    floating

    ,

  • -

       awful

    .

    layout

    .

    suit

    .

    tile

    ,

  • -

       awful

    .

    layout

    .

    suit

    .

    tile

    .

    left

    ,

  • -

       awful

    .

    layout

    .

    suit

    .

    tile

    .

    bottom

    ,

  • -

       awful

    .

    layout

    .

    suit

    .

    tile

    .

    top

    ,

  • +--

       awful

    .

    layout

    .

    suit

    .

    floating

    ,

  • +--

       awful

    .

    layout

    .

    suit

    .

    tile

    ,

  • +--

       awful

    .

    layout

    .

    suit

    .

    tile

    .

    left

    ,

  • +--

       awful

    .

    layout

    .

    suit

    .

    tile

    .

    bottom

    ,

  • +--

       awful

    .

    layout

    .

    suit

    .

    tile

    .

    top

    ,

  •     awful

    .

    layout

    .

    suit

    .

    fair

    ,

  •     awful

    .

    layout

    .

    suit

    .

    fair

    .

    horizontal

    ,

  •     awful

    .

    layout

    .

    suit

    .

    spiral

    ,

  •     awful

    .

    layout

    .

    suit

    .

    spiral

    .

    dwindle

    ,

  •     awful

    .

    layout

    .

    suit

    .

    max

    ,

  •     awful

    .

    layout

    .

    suit

    .

    max

    .

    fullscreen

    ,

  • -

       awful

    .

    layout

    .

    suit

    .

    magnifier

  • +--

       awful

    .

    layout

    .

    suit

    .

    magnifier

  • }

  • --

    }}}

  • 这里是主题,终端,以及常用布局的个人设置。

    修正补丁

    再次通过对比补丁文件与 4.2 文件,发现 38 行区块是要删除的东西不匹配,而 55 行区块则是上下文与要删除的内容均不匹配,导致不能应用补丁,于是手动修改补丁

  • $

    vim

    mypatch

    .

    patch

  • ---

    rc

    .

    lua

    .

    3.5

     

    2018

    -

    05

    -

    12

    19

    :

    15

    :

    54.922286085

    +

    0800

  • +++

    rc

    .

    lua

    .

    myconfig

    2018

    -

    05

    -

    12

    19

    :

    13

    :

    35.057911463

    +

    0800

  • @@

    -

    38

    ,

    10

    +

    38

    ,

    10

    @@

  • --

    {{{

    Variable

    definitions

  • --

    Themes

    define

    colours

    ,

    icons

    ,

    font

    and

    wallpapers

    .

  • -

    beautiful

    .

    init

    (

    gears

    .

    filesystem

    .

    get_themes_dir

    ()

    ..

    "default/theme.lua"

    )

  • +

    beautiful

    .

    init

    (

    "~/.config/awesome/default/theme.lua"

    )

  • --

    This

    is

    used later

    as

    the

    default

    terminal

    and

    editor to run

    .

  • -

    terminal

    =

    "xterm"

  • +

    terminal

    =

    "xfce4-terminal"

  • editor

    =

    os

    .

    getenv

    (

    "EDITOR"

    )

    or

    "nano"

  • editor_cmd

    =

    terminal

    ..

    " -e "

    ..

    editor

  • @@

    -

    55

    ,

    18

    +

    55

    ,

    18

    @@

  • --

    Table

    of layouts to cover

    with

    awful

    .

    layout

    .

    inc

    ,

    order matters

    .

  • awful

    .

    layout

    .

    layouts

    =

    {

  • -

       awful

    .

    layout

    .

    suit

    .

    floating

    ,

  • -

       awful

    .

    layout

    .

    suit

    .

    tile

    ,

  • -

       awful

    .

    layout

    .

    suit

    .

    tile

    .

    left

    ,

  • -

       awful

    .

    layout

    .

    suit

    .

    tile

    .

    bottom

    ,

  • -

       awful

    .

    layout

    .

    suit

    .

    tile

    .

    top

    ,

  • +--

       awful

    .

    layout

    .

    suit

    .

    floating

    ,

  • +--

       awful

    .

    layout

    .

    suit

    .

    tile

    ,

  • +--

       awful

    .

    layout

    .

    suit

    .

    tile

    .

    left

    ,

  • +--

       awful

    .

    layout

    .

    suit

    .

    tile

    .

    bottom

    ,

  • +--

       awful

    .

    layout

    .

    suit

    .

    tile

    .

    top

    ,

  •     awful

    .

    layout

    .

    suit

    .

    fair

    ,

  •     awful

    .

    layout

    .

    suit

    .

    fair

    .

    horizontal

    ,

  •     awful

    .

    layout

    .

    suit

    .

    spiral

    ,

  •     awful

    .

    layout

    .

    suit

    .

    spiral

    .

    dwindle

    ,

  •     awful

    .

    layout

    .

    suit

    .

    max

    ,

  •     awful

    .

    layout

    .

    suit

    .

    max

    .

    fullscreen

    ,

  • -

       awful

    .

    layout

    .

    suit

    .

    magnifier

    ,

  • +--

       awful

    .

    layout

    .

    suit

    .

    magnifier

    ,

  •     awful

    .

    layout

    .

    suit

    .

    corner

    .

    nw

    ,

  •    

    --

    awful

    .

    layout

    .

    suit

    .

    corner

    .

    ne

    ,

  •    

    --

    awful

    .

    layout

    .

    suit

    .

    corner

    .

    sw

    ,

  • ....

  • ....

  • 输出省略显示,有兴趣的读者可以仔细与rc.lua.rej 文件对比,看看笔者是怎样改的。

    再次应用补丁

  • $

    patch

    rc

    .

    lua

    .

    4.2

    -

    i mypatch

    .

    patch

    -

    o rc

    .

    lua

  • patching

    file

    rc

    .

    lua

    (

    read

    from

    rc

    .

    lua

    .

    4.2

    )

  • Hunk

    #

    1

    succeeded at

    41

    (

    offset

    3

    lines

    ).

  • Hunk

    #

    2

    succeeded at

    57

    with

    fuzz

    2

    (

    offset

    2

    lines

    ).

  • Hunk

    #

    3

    succeeded at

    101

    with

    fuzz

    1

    (

    offset

    5

    lines

    ).

  • Hunk

    #

    4

    succeeded at

    276

    with

    fuzz

    2

    (

    offset

    29

    lines

    ).

  • $

    cp

    rc

    .

    lua

    ~

    /.config/

    awesome

    /

    rc

    .

    lua  

    ### 打完补丁直接使用

  • 总结

    diff 与 patch 配合使用,能当增量备份,而且还可以将补丁分发给他人使用,而且在日常的软件包打补丁也具有重要的意义,特别是内核补丁或者一些驱动补丁,打补丁遇到错误时候可以尝试自己修改,已满足自身特殊要求,修改的时候一定要抓住 2 个非常重要的要素:

    ☉ 要修改的内容是否匹配?特别是要删除的☉ 上下文是否满足,特别是距离要修改的地方前后一行,以及上下文的行数是否满足,默认是 3 行上下文