Nehmen wir an, ich habe eine 4-GB-Datei abc
auf meinem lokaler Computer. Ich habe es über SFTP auf einen entfernten Server hochgeladen. Es hat einige Stunden gedauert.
Jetzt habe ich die Datei lokal geringfügig geändert (wahrscheinlich maximal 50 MB, aber keine aufeinander folgenden Bytes in dieser Datei). und speicherte es in abc2
. Ich habe auch die Originaldatei abc
auf meinem lokalen Computer gespeichert.
Wie berechnet man einen binären Diff von abc
und abc2
?
Anwendungen:
-
Ich konnte nur eine
patch
-Datei (wahrscheinlich max. 100 MB) an senden der entfernte Server, anstatt die gesamteabc2
-Datei erneut hochzuladen (es würde wieder einige Stunden dauern!) undabc2
auf dem entfernten Server neu zu erstellen Server nur vonabc
undpatch
. -
Lokal konnte ich nur 8 GB speichern, anstatt 8 GB für die Sicherung von
abc
undabc2
zu verschwendenabc
+patch
, daher würde < nur 4100 MB benötigt.
Wie geht das?
PS: Für Text kenne ich diff
, aber hier suche ich Etwas, das für jedes rohe Binärformat funktionieren könnte, es könnte Zip-Dateien oder ausführbare Dateien oder sogar andere Dateitypen sein.
PS2: Wenn möglich, möchte ich ; Ich weiß, dass es Änderungen zwischen zwei Computern auf effiziente Weise replizieren kann (keine Daten erneut senden, die sich nicht geändert haben), aber hier möchte ich wirklich eine patch
-Datei haben, die später reproduzierbar ist, wenn Ich habe sowohl abc
als auch patch
.
Antwort
Für die zweite Anwendung / Ausgabe würde ich ein deduplizierendes Sicherungsprogramm wie restic
oder borgbackup
verwenden, anstatt es zu versuchen um „Patches“ oder Diffs manuell zu verfolgen. Mit dem Sicherungsprogramm restic
können Sie Verzeichnisse von mehreren Computern in demselben Sicherungsrepository sichern und die Sicherungsdaten sowohl zwischen Dateifragmenten eines einzelnen Computers als auch zwischen Computern deduplizieren. (Ich habe keine Benutzererfahrung mit borgbackup
, daher kann ich nichts über dieses Programm sagen.)
Berechnen und Speichern eines Unterschieds der abc
und abc2
Dateien können mit rsync
erstellt werden.
Dies ist ein Beispiel mit abc
und abc2
von 153 MB. Die Datei abc2
wurde durch Überschreiben von geändert erste 2,3 MB der Datei mit einigen anderen Daten:
$ ls -lh total 626208 -rw-r--r-- 1 kk wheel 153M Feb 3 16:55 abc -rw-r--r-- 1 kk wheel 153M Feb 3 17:02 abc2
Wir erstellen Patch zum Transformieren von abc
in abc2
und nennen Sie es abc-diff
:
$ rsync --only-write-batch=abc-diff abc2 abc
$ ls -lh total 631026 -rw-r--r-- 1 kk wheel 153M Feb 3 16:55 abc -rw------- 1 kk wheel 2.3M Feb 3 17:03 abc-diff -rwx------ 1 kk wheel 38B Feb 3 17:03 abc-diff.sh -rw-r--r-- 1 kk wheel 153M Feb 3 17:02 abc2
Die generierte Datei abc-diff
ist der tatsächliche Unterschied (Ihre „Patch-Datei“), während abc-diff.sh
istEin kurzes Shell-Skript, das rsync
für Sie erstellt:
$ cat abc-diff.sh rsync --read-batch=abc-diff ${1:-abc}
Dieses Skript ändert abc
so, dass es angesichts der Datei iv id = „f91b090ab2 mit abc2
identisch wird „>
:
$ md5sum abc abc2 be00efe0a7a7d3b793e70e466cbc53c6 abc 3decbde2d3a87f3d954ccee9d60f249b abc2 $ sh abc-diff.sh $ md5sum abc abc2 3decbde2d3a87f3d954ccee9d60f249b abc 3decbde2d3a87f3d954ccee9d60f249b abc2
Die Datei abc-diff
kann jetzt an eine andere Stelle übertragen werden, an der Sie abc
haben. Mit dem Befehl rsync --read-batch=abc-diff abc
würden Sie den Patch auf die Datei abc
anwenden und ihren Inhalt so umwandeln, dass er dem von abc2
-Datei auf dem System, auf dem Sie den Diff erstellt haben.
Das erneute Anwenden des Patches ein zweites Mal scheint sicher. Es gibt weder Fehlermeldungen noch ändert sich der Inhalt der Datei (die MD5-Prüfsumme ändert sich nicht).
Beachten Sie, dass es keine Möglichkeit gibt, die Anwendung einfach rückgängig zu machen, wenn Sie keinen expliziten „Reverse Patch“ erstellen
Ich habe auch getestet, wie die 2,3-MB-Änderung an eine andere Stelle in den abc2
-Daten geschrieben wurde, etwas weiter unten (bei ungefähr 50) MB) sowie zu Beginn. Der generierte „Patch“ war 4,6 MB groß, was darauf hindeutet, dass nur die geänderten Bits im Patch gespeichert wurden.
Kommentare
- Vielen Dank @Kusalananda, es ‚ ist großartig! PS:
rsync --read-batch=abc-diff ${1:-abc}
(automatisch generiertes .sh-Skript) gabremote destination is not allowed with --read-batch
rsync error: syntax or usage error (code 1) at main.c(1326) [Receiver=3.1.2]
, aberrsync --read-batch=abc-diff abc
hat erfolgreich funktioniert.Was ist der Unterschied zwischen diesen beiden ähnlichen Befehlen? - 2/2 Gibt es eine Möglichkeit,
abc
als Eingabe zu verwenden und den Patch mit--read-batch
, aber nicht ändernabc
“ an Ort und Stelle „, sondern in eine neue Datei ausgebenabc3
? (wenn möglich alle mitrsync
, ohne Piping, so dass es problemlos unter Linux und Windows funktioniert, auf denen auchrsync.exe
verfügbar ist) - @Basj Die Befehle würden verschiedene Dinge tun, wenn
$1
einen Wert hätte.${1:-abc}
bedeutet, dass “ den ersten Positionsparameter ($1
) verwendet, es sei denn, es ist ‚ ist leer oder undefiniert. Verwenden Sie für den Fall, dass ‚ leer oder undefiniert ist,abc
stattdessen „. Ich ‚ gehe davon aus, dass$1
einen Wert hatte, als Sie es versuchten, möglicherweise etwas, das es als a interpretierte Remote-Zieladresse. - @Basj Ich ‚ bin nicht ganz sicher, ob dies möglich ist, aber ich ‚ ll Schauen Sie morgen nach dem Schlafengehen nach.
- Vielen Dank für Ihre Antwort zu
${1:-abc}
. Es ist wahrscheinlich fehlgeschlagen, weil ich es unter Windows versucht habe (ich ‚ verwende rsync sowohl unter Linux für meinen entfernten Server als auch unter Windows lokal). Aber ‚ ist perfekt, darsync --read-batch=abc-diff abc
funktioniert 🙂
Antwort
Wie berechnet man einen binären Diff von abc und abc2?
Verwenden von bsdiff / bspatch oder xdelta und anderen.
$ bsdiff older newer patch.bin # patch.bin is created [...] $ bspatch older newer patch.bin # newer is created
Diese Ermahnungen aus den Manpages sind jedoch zu beachten:
-
bsdiff
verwendet Speicher, der 17-mal so groß ist wie oldfile und erfordert eine absolute Mindestgröße des Arbeitssatzes, die das 8-fache der Größe von oldfile beträgt. -
bspatch
verwendet Speicher, der der Größe von oldfile plus der Größe von newfile entspricht, kann jedoch einen sehr kleinen Arbeitssatz ohne dramatischen Leistungsverlust tolerieren.
Kommentare
- Können Sie möglicherweise ein Beispiel zeigen?
- Vielen Dank für Ihre Antwort.
bsdiff uses memory equal to 17 times the size of oldfile
, daher funktioniert ‚ normalerweise nicht für 4-GB-Dateien (zumindest auf meinem 8-GB-RAM-Computer). - @Basj Was möglich ist, ist, die 4-GB-Datei in kleinere (z. B. jeweils 128 MB) zu zerlegen und einzelne Deltas zu erstellen. Dies könnte in ein Skript eingeschlossen werden. chopped-bsdiff: Zerhacke die Dateien, mache paarweise bsdiffs, tariere diese in ein Archiv. chopped-bspatch: Lesen Sie paarweise Patches aus dem Archiv, wenden Sie sie auf Teile der Eingabedatei an, verketten Sie die Ausgabe.
- @Kaz Ich sehe, aber ich ‚ suche mehr Ein sofort einsatzbereites Tool, das unabhängig von der Größe in einer Zeile aufgerufen werden kann (
mydiff abc abc2 > patchfile
undmypatch abc patchfile > abc3
). Wenn ich in 128-MB-Blöcke zerlege, was passiert dann, wenn die ersten 1 GBabc
== die letzten (nachfolgenden) 1 GBabc2
? Wenn wir ‚abc-first128mb
mitabc2-first128mb
vergleichen, wird keine Übereinstimmung gefunden möglicherweise nicht effizient?
Antwort
Haben Sie versucht, nur diff
, um die Dateien als Text zu behandeln:
diff -ua abc abc2
Wie hier erläutert .
-
-u
gibt NUM-Zeilen (Standard 3) mit einheitlichem Kontext aus -
-a
Behandle alle Dateien als Text.
Dies sollte dir einen Patch bringen. Der Nachteil dabei ist, dass die „Zeilen“ ziemlich lang sein können und das den Patch aufblähen könnte.
Kommentare
- Ups, ja, Sie tun nicht ‚ möchte eigentlich nicht die
n
. Ich ‚ bin interessiert zu wissen, ob es funktioniert, da ich ‚ nicht sicher bin, wie lange die “ lines “ wird sein. - Vielen Dank für Ihren Kommentar! Ich habe zwei sehr ähnliche 256-MB-Dateien
abc
undabc2
erstellt. Dann habe ichdiff -ua abc abc2 > patch
versucht, dann habe ichabc
nachabc3
kopiert und versucht,abc2
dankabc3
undpatch
:patch abc3 < patch
, aber es hat nicht funktioniert: Am Ende warabc3
nur 1 KB anstelle von 256 MB. Irgendeine Idee? - Hmmm, ich bin mir nicht sicher, was passiert ist. Ich habe es einfach auf meiner Maschine gemacht und es hat besser funktioniert als ich erwartet hatte.Ich habe eine 382M-Datei, die zufällige Ganzzahlen waren, binär in eine Datei geschrieben. Ich habe 3 Bytes darin geändert und das Diff und Patch gemacht und es hat funktioniert. Die resultierenden Dateien waren md5sum gleich.
- Wenn eine große Datei kein Byte
0x0a
hat, dh Zeilenumbruch oder sehr wenige, würde dies vermutlich nicht ‚ funktioniert nicht so gut, es wäre interessant zu testen. - Oh, sicher. Sie können mit
wc -l
eine fundierte Vermutung für eine Binärdatei anstellen, die nach Zeilenumbrüchen sucht und meiner Erfahrung nach sehr schnell ausgeführt wird. Ich würde erwarten, dass eine beliebige Binärdatei ziemlich gut funktioniert. Zum Beispiel fand ich auf meinem Computer einen 252M mp4 mit 1,2 Millionen “ Zeilen “ und einen 59M.deb
mit ungefähr 230 KB, also durchschnittliche “ Zeilen “ mit weniger als 220 Byte bzw. 258 Byte. Ich ‚ verstehe nicht, warum diese Dateien so anders sind als andere, aber Sie könnten definitiv Pech haben. In der Praxis vermute ich, dass es ziemlich gut funktionieren würde und wenn nicht, ist es ‚ immer noch ein lustiger Hack.
Antwort
Verwenden Sie xdelta , es wurde genau für diese Art von Verwendung erstellt. Basierend auf VCDIFF (RFC 3284) in den neuesten Versionen.
Kommentare
- Der Link funktioniert nicht (gibt es eine andere URL?). Sie können auch in einigen Zeilen ein Beispiel hinzufügen, um zu zeigen, wie: 1) die Datei diff
patch
berechnet und 2)abc2
wiederhergestellt wird , nurabc
undpatch
? - Entschuldigung, feste URL
- Danke @vonbrand . Hätten Sie ein solches Beispiel?
Antwort
Ergänzungen zu anderen Antworten gemäß meinen Tests:
Mit diff
habe ich zwei sehr ähnliche 256-MB-Dateien erstellt abc
und abc2
. Dann erstellen wir die Diff-Datei:
diff -ua abc abc2 > abc-abc2.diff
Versuchen wir nun, abc2
dank der wiederherzustellen Original abc
-Datei und abc-abc2.diff
:
cp abc abc3 patch abc3 < abc-abc2.diff
oder
cp abc abc3 patch abc3 -i abc-abc2.diff
oder
patch abc -i abc-abc2.diff -o abc3
Es funktioniert unter Linux. Ich habe es auch unter Windows versucht (patch.exe und diff.exe sind ebenfalls verfügbar), aber aus einem unbekannten Grund ist dies fehlgeschlagen: Die erstellte abc3
-Datei ist nur 1 KB anstelle von 256 MB (I „). Ich werde diese Antwort später hier aktualisieren.
Mit rsync
Wie in der akzeptierten Antwort beschrieben, funktioniert dies:
rsync --only-write-batch=abc-abc2-diff abc2 abc cp abc abc3 rsync --read-batch=abc-abc2-diff abc3
Mit rdiff
Wie in beschrieben Antwort , dies ist auch eine Lösung:
rdiff signature abc abc-signature rdiff delta abc-signature abc2 abc-abc2-delta rdiff patch abc abc-abc2-delta abc3
Getestet auch unter Windows mit rdiff.exe von hier und es funktioniert.
Kommentare
- Ich ‚ vermute das Der Patch ist unter Windows fehlgeschlagen, da die Eingabedatei im Textmodus “ “ gelesen wurde, der das Dateiende signalisiert, wenn eine STEUERUNG auftritt -Z (Byte 0x18) in der Eingabedatei. Dies ist ein Legacy-Modus aus frühen DOS-Tagen, als das Verzeichnis die Länge von nicht aufzeichnete Die Datei und damit die Dateilänge wurden basierend auf der Anzahl der 512-Byte-Sektoren berechnet. Wenn Sie
patch
anweisen können, die Datei im Binärmodus zu öffnen, sollte ‚ diesen Fehler nicht haben.