Eine Datei in 64-MB-Blöcken hashen?

Eine Datei in 64-MB-Blöcken hashen?

Ich habe eine sehr große Datei (200 GB). Anscheinend wurde sie beim Übertragen nicht richtig kopiert. Der SHA1-Hash ist auf beiden unterschiedlich. Gibt es eine Möglichkeit, die Datei in Blöcke (z. B. 1 MB oder 64 MB) aufzuteilen und für jeden Block einen Hash auszugeben? Dann vergleichen/korrigieren?

Vielleicht schreibe ich einfach schnell eine App dafür.

Antwort1

Diese „schnelle App“ gibt es bereits und sie ist relativ weit verbreitet: rsync. Natürlich kann rsync noch viel mehr, aber was Sie wollen, ist ziemlich einfach:

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

Standardmäßig wird ssh (oder bei einer sehr alten Version rsh) verwendet, um die Verbindung herzustellen und die Daten zu übertragen. Andere Methoden sind ebenfalls möglich.

Die von mir übergebenen Optionen sind:

  • -c– Überspringen basierend auf Prüfsummen, nicht Dateigröße/Mtime. Standardmäßig optimiert und überspringt rsync Übertragungen, bei denen Größe und Mtime übereinstimmen. -czwingt es, die Prüfsumme zu berechnen (was in Bezug auf E/A eine aufwändige Operation ist). Beachten Sie, dass dies eine blockbasierte Prüfsumme ist (es sei denn, Sie weisen es an, nur ganze Dateien zu verarbeiten) und es werden nur die beschädigten Blöcke übertragen. Die Blockgröße wird automatisch gewählt, kann aber überschrieben werden -B(ich bezweifle, dass es dafür einen Grund gibt).
  • -v— ausführlich, gibt einige Details an (an welcher Datei gearbeitet wird)
  • -P— aktiviert sowohl teilweise Dateien (damit die Arbeit nicht weggeworfen wird, wenn die Arbeit zur Hälfte fertig ist) als auch einen Fortschrittsbalken.
  • --inplace— Aktualisieren Sie die vorhandene Datei, nicht eine temporäre Datei (die dann die Originaldatei ersetzen würde). So sparen Sie sich eine temporäre Datei mit 200 GB. Impliziert auch Teildateien, was -Pteilweise redundant ist.

Übrigens: Ich bin nicht sicher, wie Sie die ursprüngliche Übertragung durchgeführt haben, aber wenn es SFTP/SCP war, stimmt etwas nicht – diese schützen vollständig vor Beschädigungen im Netzwerk. Sie sollten wirklich die Ursache herausfinden. Defekter RAM ist ein relativ häufiges Problem.

Antwort2

Wenn Sie die Datei über eine Netzwerkverbindung auf einen anderen Rechner übertragen möchten,Verwenden Sie rsync.

Wenn Sie sich ein Bild von den Unterschieden machen möchten, ist es am einfachsten, die beiden Versionen auf derselben Maschine zu haben. Wenn Sie das nicht möchten, weil die Bandbreite zu teuer ist, können Sie auf folgende Weise Dateiblöcke überprüfen.

Bei dieser Methode wird head -cdie Dateiposition dort belassen, wo sie aufgehört hat, und die Größe wird vorab berechnet, um zu wissen, wo die Schleife enden soll.

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

Bei dieser Methode wird head -cdie Dateiposition dort belassen, wo sie aufgehört hat, und sie wird verwendet, cksumum die Größe jedes Blocks zu ermitteln (ein kurzer Block zeigt das Ende der Datei an).

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

Diese Methode ruft ddden Sprung zur gewünschten Startposition für jeden Block auf.

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

Antwort3

Sie sollten sich wahrscheinlich Folgendes ansehen split:

Hier ist die Manpage mit Beispielen:

https://ss64.com/bash/split.html

verwandte Informationen