
我有一個非常大的檔案(200GB)。顯然,當我將其轉移過來時,它沒有正確複製。兩者的 sha1 哈希值不同。有沒有辦法將檔案分成區塊(例如 1MB 或 64MB)並為每個區塊輸出雜湊值?然後比較/修復?
我可能只是寫一個快速的應用程式來做到這一點。
答案1
這個「快速應用程式」已經存在,並且相對常見:rsync。當然,rsync 的作用遠不止於此,但您想要的相當簡單:
rsync -cvP --inplace user@source:src-path-to-file dest-path-to-file # from the destination
rsync -cvP --inplace src-path-to-file user@dest:dest-path-to-file # from the source
預設情況下,將使用 ssh(或可能是 rsh,在非常舊的版本上)來建立連線並傳輸資料。其他方法也是可能的。
我通過的選項是:
-c
— 根據校驗和跳過,而不是檔案大小/運行時間。預設情況下,rsync 會最佳化並跳過大小和運行時間匹配的傳輸。-c
強制它計算校驗和(就 I/O 而言,這是一項昂貴的操作)。請注意,這是基於區塊的校驗和(除非您告訴它僅執行整個檔案),並且它只會傳輸損壞的區塊。區塊大小是自動選擇的,但可以被覆蓋-B
(我懷疑有任何理由這樣做)。-v
— 詳細,將提供一些詳細資訊(正在處理哪個文件)-P
— 開啟兩個部分檔案(因此,如果完成一半,它不會放棄工作)和進度條。--inplace
— 更新現有文件,而不是臨時文件(隨後將取代原始文件)。讓您免於擁有 200GB 的臨時檔案。也意味著部分文件,因此這-P
是部分冗餘的。
順便說一句:我不確定你是如何進行原始傳輸的,但如果它是 sftp/scp,那麼有些事情就非常錯誤了——它們完全防止網路上的任何損壞。你確實應該找出原因。 RAM 有缺陷是一種相對常見的情況。
答案2
如果您想透過網路連線將檔案重新傳輸到另一台機器,使用rsync。
如果您想了解差異在哪裡,最簡單的方法是將兩個版本放在同一台電腦上。如果您因為頻寬太昂貴而不想這樣做,可以透過以下方法檢查檔案區塊。
此方法依賴head -c
將檔案位置保留在其停止的位置,並預先計算大小以了解在哪裡結束循環。
n=$(($(wc -c <very_large_file) / (64*1024*1024) + 1))
i=0
while [ $i -gt $n ]; do
head -c 64m | sha256sum
i=$((i+1))
done <very_large_file
此方法依賴head -c
將檔案位置保留在其停止的位置,並用於cksum
查找每個區塊的大小(短區塊表示檔案末端)。
while true; do
output=$(head -c 64m | cksum)
size=${output#* }; size=${output%% *}
if [ $size -eq 0 ]; then break; fi
echo "$output"
done <very_large_file
此方法呼叫dd
跳到每個區塊所需的開始位置。
n=$(($(wc -c <very_large_file) / (64*1024*1024) + 1))
i=0
while [ $i -gt $n ]; do
dd if=very_large_file ibs=64m skip=$i count=1 | sha256sum
i=$((i+1))
done <very_large_file