Ř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éhoabc2souboru (bude to trvat znovu několik hodin!), a znovu vytvořteabc2na vzdáleném serveru server pouze zabcapatch. -
Lokálně bych místo plýtvání 8 GB zálohováním
abcaabc2mohl 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-batchrsync error: syntax or usage error (code 1) at main.c(1326) [Receiver=3.1.2], alersync --read-batch=abc-diff abcfungoval úspěšně.Jaký je rozdíl mezi těmito dvěma podobnými příkazy? - 2/2 Existuje způsob, jak vzít
abcjako vstup, použít patchdiff-abcs--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.exek dispozici) - @Basj Příkazy by dělaly různé věci, kdyby
$1mě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$1mě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 abcfunguje 🙂
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:
-
bsdiffpoužívá paměť rovnou 17násobku velikosti oldfile a vyžaduje absolutní minimální velikost pracovní sady 8krát větší než oldfile . -
bspatchpouží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 .
-
-uvýstup NUM (výchozí 3) řádky sjednoceného kontextu -
-azachá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
nnechce. ‚ 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
abcaabc2. Pak jsem zkusildiff -ua abc abc2 > patch, potom jsem zkopírovalabcdoabc3a pokusil jsem se obnovitabc2díkyabc3apatch:patch abc3 < patch, ale nefungovalo to: na konciabc3byl 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.debkteré 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
patcha 2) obnovitabc2, uvedeno pouzeabcapatch? - 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 oldfiletakže to obvykle ‚ obvykle nefunguje pro 4GB soubory (alespoň na mém 8GB RAM stroji).mydiff abc abc2 > patchfileamypatch 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-first128mbsabc2-first128mb, nebude nalezena žádná shoda, takže nemusí být efektivní?