Řekněme, že mám 4 GB soubor abc
místní počítač. Nahrál jsem to na vzdálený server přes SFTP, trvalo to několik hodin.
Nyní jsem lokálně mírně upravil soubor (maximálně asi 50 MB, ale ne po sobě jdoucích bajtů), a uložil jsem jej do abc2
. Původní soubor abc
jsem si také ponechal v místním počítači.
Jak vypočítat binární rozdíl abc
a abc2
?
Aplikace:
-
Mohu odeslat pouze soubor
patch
(pravděpodobně max. 100 MB) vzdálený server, namísto opětovného načtení celéhoabc2
souboru (bude to trvat znovu několik hodin!), a znovu vytvořteabc2
na vzdáleném serveru server pouze zabc
apatch
. -
Lokálně bych místo plýtvání 8 GB zálohováním
abc
aabc2
mohl uložit pouzeabc
+patch
, takže by to trvalo < pouze 4100 MB.
Jak na to?
PS: pro text znám diff
, ale tady hledám něco, co by fungovalo pro jakýkoli surový binární formát, mohly by to být soubory zip nebo spustitelné soubory nebo dokonce jiné typy souborů.
PS2: Pokud je to možné, nechci použít rsync
; Vím, že dokáže efektivně replikovat změny mezi 2 počítači (ne znovu odesílat data, která se nezměnila), ale tady opravdu chci mít soubor patch
, který je později reprodukovatelný, pokud Mám abc
a patch
.
odpověď
Pro druhou aplikaci / problém bych místo pokusu použil deduplikační zálohovací program jako restic
nebo borgbackup
pro ruční sledování „oprav“ nebo rozdílů. Zálohovací program restic
umožňuje zálohovat adresáře z více počítačů do stejného úložiště záloh a deduplikovat tak data zálohy mezi fragmenty souborů z jednotlivých počítačů i mezi nimi. (Nemám žádné uživatelské zkušenosti s borgbackup
, takže o tomto programu nemohu nic říci.)
Výpočet a uložení rozdílu abc
a abc2
lze vytvořit pomocí rsync
.
Toto je příklad s abc
a abc2
s 153 MB. Soubor abc2
byl změněn přepsáním prvních 2,3 MB souboru s některými dalšími údaji:
$ 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
Vytvoříme oprava pro transformaci abc
na abc2
a nazývání 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
Vygenerovaný soubor abc-diff
je skutečný rozdíl (váš „soubor opravy“), zatímco abc-diff.sh
jekrátký skript prostředí, který pro vás rsync
vytvoří:
$ cat abc-diff.sh rsync --read-batch=abc-diff ${1:-abc}
Tento skript upraví abc
tak, aby se stal identickým s abc2
, vzhledem k souboru abc-diff
:
$ md5sum abc abc2 be00efe0a7a7d3b793e70e466cbc53c6 abc 3decbde2d3a87f3d954ccee9d60f249b abc2 $ sh abc-diff.sh $ md5sum abc abc2 3decbde2d3a87f3d954ccee9d60f249b abc 3decbde2d3a87f3d954ccee9d60f249b abc2
Soubor abc-diff
nyní lze přenést kamkoli jinde máte abc
. Pomocí příkazu rsync --read-batch=abc-diff abc
byste opravu aplikovali na soubor abc
a transformovali jeho obsah tak, aby byl stejný jako abc2
soubor v systému, kde jste vytvořili rozdíl.
Opětovné použití opravy se zdá být bezpečné. Neexistují žádné chybové zprávy ani se nemění obsah souboru (kontrolní součet MD5 se nemění).
Upozorňujeme, že pokud nevytvoříte explicitní „reverzní opravu“, neexistuje způsob, jak aplikaci snadno vrátit zpět. opravy.
Také jsem otestoval zápis úpravy 2,3 MB na nějaké jiné místo v datech abc2
, o kousek dál (asi 50 MB), stejně jako na začátku. Vygenerovaná „oprava“ byla velká 4,6 MB, což naznačuje, že v opravě byly uloženy pouze upravené bity.
Komentáře
- Mnohokrát děkujeme @Kusalananda, je to ‚ skvělé! PS:
rsync --read-batch=abc-diff ${1:-abc}
(automaticky generovaný skript .sh) dalremote destination is not allowed with --read-batch
rsync error: syntax or usage error (code 1) at main.c(1326) [Receiver=3.1.2]
, alersync --read-batch=abc-diff abc
fungoval úspěšně.Jaký je rozdíl mezi těmito dvěma podobnými příkazy? - 2/2 Existuje způsob, jak vzít
abc
jako vstup, použít patchdiff-abc
s--read-batch
, ale neměníabc
“ na místě „, ale spíše výstup do nového souboruabc3
? (pokud je to možné vše srsync
, bez použití potrubí, takže to bude fungovat snadno na Linuxu i Windows, který má takérsync.exe
k dispozici) - @Basj Příkazy by dělaly různé věci, kdyby
$1
měl hodnotu.${1:-abc}
znamená “ použít první poziční parametr ($1
), pokud ‚ je prázdný nebo nedefinovaný. V případě, že je ‚ prázdný nebo nedefinovaný, použijte místo tohoabc
„. ‚ m za předpokladu, že$1
měl hodnotu, když jste to zkusili, možná něco, co to interpretovalo jako vzdálená cílová adresa. - @Basj I ‚ si nejsem úplně jistý, zda je to možné, ale ‚ ll podívejte se zítra po spánku.
- Děkujeme za odpověď týkající se
${1:-abc}
. Pravděpodobně se to nezdařilo, protože jsem to zkusil na Windows (‚ m používám rsync jak na Linuxu pro můj vzdálený server, tak i lokálně Windows). Ale ‚ je perfektní, protožersync --read-batch=abc-diff abc
funguje 🙂
Odpověď
Jak vypočítat binární rozdíl abc a abc2?
Použití bsdiff / bspatch nebo xdelta a dalších.
$ bsdiff older newer patch.bin # patch.bin is created [...] $ bspatch older newer patch.bin # newer is created
Je však třeba si uvědomit tato upozornění z manuálových stránek:
-
bsdiff
používá paměť rovnou 17násobku velikosti oldfile a vyžaduje absolutní minimální velikost pracovní sady 8krát větší než oldfile . -
bspatch
používá paměť rovnou velikosti oldfile plus velikosti newfile , ale může tolerovat velmi malou pracovní sadu bez dramatické ztráty výkonu.
Komentáře
Odpověď
Zkusili jste jen vynucení diff
zacházet se soubory jako s textem:
diff -ua abc abc2
Jak je vysvětleno zde .
-
-u
výstup NUM (výchozí 3) řádky sjednoceného kontextu -
-a
zacházet se všemi soubory jako s textem
To by vám mělo dát opravu. Nevýhodou je, že „řádky“ mohou být poměrně dlouhé a to by mohlo nafouknout náplast.
Komentáře
- Jejda, jo, ‚ ve skutečnosti
n
nechce. ‚ Mám zájem vědět, jestli to funguje, protože si ‚ nejsem jistý, jak dlouho “ lines “ bude. - Děkujeme za váš komentář! Vytvořil jsem dva velmi podobné soubory 256 MB
abc
aabc2
. Pak jsem zkusildiff -ua abc abc2 > patch
, potom jsem zkopírovalabc
doabc3
a pokusil jsem se obnovitabc2
díkyabc3
apatch
:patch abc3 < patch
, ale nefungovalo to: na konciabc3
byl místo 256 MB pouze 1 kB. Máte nějaký nápad? - Hmmm, nejste si jisti, co se stalo. Právě jsem to udělal na svém stroji a fungovalo to lépe, než jsem čekal.Vzal jsem soubor 382M, který byl náhodná celá čísla zapsaná binárně do souboru. Změnil jsem v něm 3 bajty a udělal diff a patch a fungovalo to. Výsledné soubory byly stejné jako md5sum.
- Pokud velký soubor nemá žádný bajt
0x0a
, tj. Nový řádek, nebo jen velmi málo, domnívám se, že by to nebylo ‚ nefunguje tak dobře, bylo by zajímavé otestovat. - Určitě. Vzdělaný odhad můžete udělat na binárním souboru s
wc -l
, který bude hledat konce řádků a podle mých zkušeností běží velmi rychle. Očekával bych, že na libovolném binárním souboru to bude fungovat docela dobře. Například na svém stroji jsem našel 252M mp4, který měl 1,2 milionu “ řádků “ a 59M.deb
které měly přibližně 230 kB, takže průměrné “ řádky “ byly méně než 220 bajtů a 258 bajtů. Nechápu ‚, proč by se tyto soubory lišily od ostatních, ale určitě byste měli smůlu. V praxi mám podezření, že by to fungovalo docela dobře, a pokud ne, je to stále ‚ stále zábavný hack.
Odpověď
Použijte xdelta , byla vytvořena přesně pro tento typ použití. Na základě VCDIFF (RFC 3284) v nejnovějších verzích.
Komentáře
- Odkaz nefunguje (existuje jiná adresa URL?). Můžete také přidat příklad na několik řádků, který ukazuje, jak: 1) vypočítat soubor diff
patch
a 2) obnovitabc2
, uvedeno pouzeabc
apatch
? - Omlouváme se, opravená URL
- děkuji @vonbrand . Máte takový příklad?
Odpověď
Doplňky k dalším odpovědím podle mých testů:
S diff
jsem vytvořil dva velmi podobné 256 MB soubory abc
a abc2
. Poté vytvořme soubor rozdílu:
diff -ua abc abc2 > abc-abc2.diff
Nyní se pokusme obnovit abc2
díky původní abc
soubor a abc-abc2.diff
:
cp abc abc3 patch abc3 < abc-abc2.diff
nebo
cp abc abc3 patch abc3 -i abc-abc2.diff
nebo
patch abc -i abc-abc2.diff -o abc3
Funguje na systému Linux. Také jsem vyzkoušel Windows (patch.exe a diff.exe jsou také k dispozici), ale z neznámého důvodu se to nezdařilo: vyprodukovaný soubor abc3
má pouze 1 kB místo 256 MB (I “ Aktualizuji tuto odpověď později zde).
S rsync
Jak je uvedeno v přijaté odpovědi, toto funguje:
rsync --only-write-batch=abc-abc2-diff abc2 abc cp abc abc3 rsync --read-batch=abc-abc2-diff abc3
s rdiff
Jak je podrobně uvedeno v tomto odpověď , toto je také řešení:
rdiff signature abc abc-signature rdiff delta abc-signature abc2 abc-abc2-delta rdiff patch abc abc-abc2-delta abc3
Testováno také na Windows s rdiff.exe z zde a funguje to.
Komentáře
- Já ‚ hádám, že oprava v systému Windows selhala, protože načítal vstupní soubor v režimu “ text „, který signalizuje konec souboru, když narazí na KONTROLU -Z (bajt 0x18) ve vstupním souboru. Toto je starší režim z prvních dnů systému DOS, kdy adresář nezaznamenával délku soubor a tak byla vypočítána délka souboru na základě počtu 512 bajtových sektorů. Pokud můžete říct
patch
, aby soubor otevřel v binárním režimu, neměla by ‚ tuto chybu mít.
bsdiff uses memory equal to 17 times the size of oldfile
takže to obvykle ‚ obvykle nefunguje pro 4GB soubory (alespoň na mém 8GB RAM stroji).mydiff abc abc2 > patchfile
amypatch abc patchfile > abc3
) bez ohledu na velikost. Pokud také nasekám na 128 MB bloky, co se stane, když první 1 GBabc
== poslední (koncové) 1 GBabc2
? Když ‚ porovnámeabc-first128mb
sabc2-first128mb
, nebude nalezena žádná shoda, takže nemusí být efektivní?