【问题标题】:Diff of two directory trees to create file/folder level patch (incl. binary files)两个目录树的差异以创建文件/文件夹级别的补丁(包括二进制文件)
【发布时间】:2011-11-22 09:49:46
【问题描述】:

有很多解决方案可以为文本文件等创建文件级补丁。我正在寻找的是一个简单的脚本/shell命令,它将比较旧版本/新版本/并给我一棵我需要复制旧版本以使其等于新版本的文件树(假设文件没有在更新中删除版本)。请注意,这两个文件夹包含二进制文件和文本文件。

以前,我们使用的是 hack:

fdupes -qrf newversion/ oldversion/ | grep "newversion" | xargs rm;

给我们留下可以打包为补丁的文件夹“newversion”。

不幸的是,结果证明这是灾难性的,因为 fdupes 不考虑文件名。

如果 fdupes 确实在比较中包含了文件名,那就太好了。

【问题讨论】:

  • 您是否只在 newversion/ 中寻找“新”文件列表而不是“修改”文件?
  • 新文件和修改文件。

标签: linux compare directory patch


【解决方案1】:

我知道已经很久了。我需要相同的解决方案。我找到了这篇文章,但这还不够。然后我发现rsync 可以在你“修补”相同副本的情况下完成这项工作,并且不需要与其他更改合并。我打算在断开连接的机器上使用它来更新 yum 镜像。我的完整解决方案涉及更多内容,并且我正在从内存中编写命令,因此一些细节可能是错误的,但核心是:

# create identical copy "copy.0"
rsync -a master/ copy.0/

# Presumably transfer copy.0/ to another machine for offline use
# but copy.0 must not mutate outside of this process or sync probably
# will not work.

# some time later update master, e.g. rsync master from upstream mirror
# mutates master in some way, changes/adds/removes remove files including
# binaries
echo -n $'\001\002' > master/new.bin
rm master/gone.bin

# generate rsync batch that can be used to ``patch`` copy.0
# to become identical to master
rsync -a --delete --itemize-changes --only-write-batch=copy.0.batch \
    master/ copy.0/
# now the file copy.0.batch contains only the deltas to be applied

# transfer the batch file to where it needs to be applied

# apply the batch to copy.0
rsync -a --delete --itemize-changes --read-batch=copy.0.batch copy.0/

这会处理删除和许多其他事情,可能权限、时间戳等,但我认为它可能不会将硬链接作为硬链接处理,并且可能会将它们创建为单独的未链接文件。 p>

【讨论】:

    【解决方案2】:

    可以要求 diff 命令输出不同的文件名。

    diff --quiet --recurse --unidirectional-new-file OLDDIR NEWDIR
    
    Files old/main and new/main differ
    Files old/main.cpp and new/main.cpp differ
    Files old/Makefile and new/Makefile differ
    Files old/sounds/popalien.wav and new/sounds/popalien.wav differ
    Files old/sounds/saucer.wav and new/sounds/saucer.wav differ
    

    当然,这不是一个很好的输出,但由于您只是在寻找新文件以打包为补丁,因此快速 sed 管道可以创造奇迹:

    diff --quiet --recurse -unidirectional-new-file OLDDIR NEWDIR | \
      sed "s/^.* and \(.*\) differ/\1/"
    

    (为便于阅读而中断)

    new/main
    new/main.cpp
    new/Makefile
    new/sounds/popalien.wav
    new/sounds/saucer.wav
    

    “and”前后的空格和前面的“differ”

    diff 的操作数的顺序有所不同,第一个参数在 ' 和 ' 的左边,第二个在后面。请注意这一点。

    另外,如果您从 NEWDIR 中删除文件,这将不会找到给定的文件,只会找到添加或更改的文件。要同时输出在任一子目录中未找到的文件的文件名,请将 --unidirection-new-file 替换为 --new-file。 (除了 --unidirectional.. 之外的所有选项都存在短选项。)

    【讨论】:

      【解决方案3】:

      diff -ruN oldversion newversion

      【讨论】:

        猜你喜欢
        • 2011-01-28
        • 2011-05-12
        • 2020-08-18
        • 1970-01-01
        • 2011-09-02
        • 1970-01-01
        • 1970-01-01
        • 2020-05-02
        • 1970-01-01
        相关资源
        最近更新 更多