获取两个目录的二进制增量编码递归差异作为 CLI 中的单个补丁文件(和在线使用)

sda*_*aau 20 command-line software-recommendation

本质上,我正在寻找一个 GNU/Linux 工具,它可以递归地遍历两个目录,找到文件更改/添加/删除;对于所有更改的文件,输出差异。这已经可以通过diff有效地用于文本文件来完成,但不能用于大型二进制文件 - 我还希望包含在最终补丁中的二进制文件之间有效的“差异”(我收集,这被称为二进制增量压缩 - 维基百科作为子集的增量编码-维基百科)。或者,换句话说,执行此“愿望清单”评论中描述的操作(来自CommandLineSyntax - xdelta - Google Project Hosting):

如果 xdelta 支持多个文件修补,那就太好了。就像是:

xdelta3 -r /path/folder1 /path/folder2 >allfilesrecursivepatch.xdelta
Run Code Online (Sandbox Code Playgroud)

用于递归比较文件夹 1 和文件夹 2 上的所有文件并为所有文件创建单个补丁文件。和:

xdelta3 -r -d /path/folder1 <allfilesrecursivepatch.xdelta
Run Code Online (Sandbox Code Playgroud)

用于在文件夹 1 中包含的所有文件上应用补丁

这个工具不存在,从Issue 21 - xdelta - Recursive directory diff support - Google Project Hosting判断),虽然有解决办法:问题页面有几个关于脚本包装器的建议,但我宁愿保持独立一个工具。

对我来说最重要的是修补“实时”文件系统目录部分,如上所示,由于我的预期用例 - 下面更详细地描述,并用bash使用git.


我希望能够在廉价的 Linux 主机/webfarm 上更新静态网站,它只允许rsync传输速度相当低的FTP 传输(所以没有等等),并且只允许 PHP 脚本执行。通常我需要从本地/客户端/主页同步到服务器/网络主机,但当然我不想每次更新页面时都上传 200 MB:)

我可以使用outlandishideas/sync · GitHub来“使用 PHP 通过 HTTP 同步目录内容”,但除了只从服务器同步到本地之外,还只发送整个文件:“不尝试发送差异;这不是 rsync”。同样,我可以使用GNU FTPsync;它可能可以处理文件的创建、修改和删除,但它有同样的问题——只会发送整个文件。

原则上,git也可以使用 - 下面的脚本生成目录testdir_oldtestdir_new,并显示git可以对它们之间的差异进行编码(在这种情况下是“删除 1024;添加 1024;修改/添加 19;修改内联 1200”,或总共 3267 个字节更改)作为“sneakernet” git bundle文件,大小为 4470 字节。但是,即使我可以说服主机安装git在那里,我仍然必须.git在虚拟主机上维护一个repo 才能干净地应用捆绑包 - 我绝对不想这样做,因为我无法避免额外的文件大小使用;此外,似乎使用 git 管理大型二进制文件 - 堆栈内存溢出需要git annexgit bup.. 放置一个像下面这样的脚本会有问题,因为git每次都会重新创建新的修订哈希,使得包不能干净地应用。

此外,由于在 PHP 中,我显然可以“在没有 exec() 的情况下 untar-gz? - 堆栈溢出”,也许值得尝试确定目录中的更改,然后仅将更改的文件打包在 a 中tar.gz,并将其发送到 PHP 脚本服务器,这会将其解压缩到目标目录。这仍然会发送整个文件,但至少它们会被压缩 - 但服务器上的删除将难以处理。

最后,二进制文件差异实用程序建议您可以将目录打包在.tar(.gz)每个目录中,然后在这些文件上运行该实用程序 - 例如(通过ExternalCompression - xdelta - Google Project Hosting):

gzip release-1.tar
gzip release-2.tar
xdelta3 -e -s release-1.tar.gz release-2.tar.gz delta-1-2.xd3
xdelta3 -d -s release-1.tar.gz delta-1-2.xd3 release-2.tar.gz
Run Code Online (Sandbox Code Playgroud)

...可能也可以使用JojoDiff /jdiff

jdiff archive0000.tar archive0001.tar archive0001.jdf
jptch archive0000.tar archive0001.jdf archive0001b.tar
Run Code Online (Sandbox Code Playgroud)

... 或与bsdiff. 但是,这需要我在虚拟主机上维护整个站点的 tar 存档,以允许补丁干净地应用到它,并且空间再次成为问题。这也会迫使我要求虚拟主机允许我安装和使用至少工具的修补部分;如果这些工具不需要我在主机上保留站点的额外 tar'd 副本,那么这可能值得再试一次。

无论如何,下面是演示提取 agit .bundle作为两个目录(或者更确切地说,同一目录的两个版本)之间的递归差异的脚本;相关的终端输出包含在评论中:

xdelta3 -r /path/folder1 /path/folder2 >allfilesrecursivepatch.xdelta
Run Code Online (Sandbox Code Playgroud)

小智 1

尝试一下git-ftp。它完全是为了这个目的而制作的。

它通过将提交 ID 存储在服务器上的日志文件中来跟踪上传的文件。它使用 Git 来确定哪些本地文件已更改。


jpa*_*cek 0

我会寻求低调的解决方案。如果我理解正确的话,您想要更新网页,并且不希望大多数网页发生变化,在这种情况下,我只会上传整个更改的文件。

这可以实现,例如。在 中mc,通过 FTP 将一个面板连接到您的虚拟主机,让其他面板显示本地版本。然后选择所有内容并复制,然后选择仅覆盖所有较新的文件(您可以一次为所有文件选择该选项)。或者使用另一个文件管理器的同步工具,我相信 krusader 有一些。除非您有仅在本地更改的大文件(它们是什么?数据库1?也许是可执行文件,但未压缩?),在我看来,二进制增量不会给您带来太多帮助。

注意 1:以这种方式同步数据库是一个坏主意。