如何从 Windows 和 Linux 上的文件夹获得相同的哈希值?

如何从 Windows 和 Linux 上的文件夹获得相同的哈希值?

我使用 7zip 来计算文件夹(带有子文件夹)的哈希值,它有两个选项:包含或不包含文件名。

然而,在 Linux 版本的 7zip 上,哈希功能尚未实现。我尝试了不同的方法复制结果,但是这些方法都不会在 Linux 和 Windows 上产生相同的结果。

结果示例:

7za.exe h -scrcsha1 myfolder在 Windows 上显示:

SHA1   for data:              D54D3168B16BFEE600C3A77E848A2A1C1DBCBC59
SHA1   for data and names:    BCE55085200581AD1774CC25AE065DE7DE60077D

,而在Linux上我有:

find . -type f -exec sha1sum "$PWD"/{} \; | sha1sum
ee44137f2462bdfea87ec824dab514f288ae3e6c  -

或者

find . -type f | xargs sha1sum | sha1sum
8f971311a28bcdee36fab0ce87a892564622db40  -

所以我无法在一个平台上使用另一个平台的结果。

(我确实验证了单个文件的结果对于两个平台是相同的。)

答案1

仅运行以下命令不一定有效:

find . -type f | xargs sha512sum | sha512sum

您可能会遇到的问题是,报告的文件顺序find在不同系统之间甚至在不同目录复制之间是不同的。

相反,尝试运行以下命令:

find . -type f | sort | xargs sha512sum | sha512sum

根据您的要求,可随意交换sha512sum其他的 - 例如:md5sum// sha1sumsha256sum

请注意,对于较大的目录树,这可能会变慢,在这种情况下,您可能更喜欢使用更复杂的脚本来遍历层次结构。


例子:

$ find . -type f | xargs sha512sum | sha512sum
097e56f6b751c1da15ce5b9dce853ffcc89e06e9cbe10a8dc0894dedb834d40dc4228c65e48bd53f136dd6a7700b0ab07e8e12e7100956db00b0d1b9ef0b9956  -

这包括最终哈希中的文件名和内容,但不包括元数据 - 修改时间、权限等......


请注意,您可以在 Windows 上使用“适用于 Linux 的 Windows 子系统find“。我刚刚安装了它,这是一个轻松的体验,并且还让我意识到了报告的订购问题。

还要注意 Linux 与 Windows 上树中的符号链接是如何处理的。

答案2

不幸的是,似乎无法重现 7-zip 生成的文件夹的哈希值。

这是因为 7z 使用 FindNextFileW() 函数来枚举目录(7z-1900src/CPP/Windows/FileFind.cpp,第 198 行)。

函数返回值的顺序无法保证,并且可能与文件系统有关(根据https://docs.microsoft.com/zh-cn/windows/win32/api/fileapi/nf-fileapi-findnextfilew)。

所以如果您想实现一个独立于平台的目录哈希函数,您应该使用统一的排序函数。

答案3

由于 Linux 无法复制 7zip 校验和,而且我没有 nodeJS,因此我安装了“Windows Subsystem for Linux”来验证从 Windows 计算机到 Synology NAS 的文件夹复制。安装 WSL 非常简单,只需按照文档

对于在 Windows 和 Linux 上实际生成相同哈希值的命令,我主要参考了如何计算目录的 MD5 校验和?,解释了如何在 Windows 和 Linux 之间对结果进行一致排序,以及如何不忽略空目录。一致排序是通过以下方式实现的LC_ALL=C

find . -type f -print0 | LC_ALL=C sort -z | xargs -r0  sha512sum | sha512sum

但是这不能处理空目录,所以这里有一个从其他答案复制的更完整的命令。它不用于-print0降低复杂性,但 Windows 不允许在文件/文件夹名称中使用换行符和此类特殊字符,所以没什么大不了的。

dir=<mydir>; (find "$dir" -type f -exec md5sum {} +; find "$dir" -type d) | LC_ALL=C sort | md5sum

最后,Synology 会创建额外的文件/文件夹用于索引,因此我还必须忽略索引文件-not -path。这是我的最后一个命令,它在 WSL 中为我的 Windows 文件夹生成了相同的校验和,在 Synology SSH 中为复制的文件夹生成了相同的校验和:

dir=.; (find "$dir" -type f -not -path '*@eaDir*' -exec sha512sum {} +; find "$dir" -type d -not -path '*@eaDir*') | LC_ALL=C sort | sha512sum

相关内容