如何從 Windows 和 Linux 上的資料夾中獲得相同的哈希值?

如何從 Windows 和 Linux 上的資料夾中獲得相同的哈希值?

我使用 7zip 來計算資料夾(帶有子資料夾)的雜湊值,它可以透過兩個選項來完成,包括或不包括檔案名稱。

然而,在 7zip 的 Linux 版本上,哈希功能並未實現。我嘗試了不同的方法複製結果,但這些方法都不會在 Linux 和 Windows 上給出相同的結果。

結果範例:

7za.exe h -scrcsha1 myfolderWindows 上的「 」給:

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  -

這包括最終哈希中的檔案名稱和內容,但不包括元資料 - 修改時間、權限等...


請注意,您可以透過使用“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

相關內容