Låt oss säga att jag har en 4 GB-fil abc på min lokal dator. Jag har laddat upp den till en avlägsen server via SFTP, det tog några timmar.
Nu har jag modifierat filen lite (troligen 50 MB maximalt, men inte på varandra följande byte i den här filen) lokalt, och sparade den i abc2. Jag behöll också originalfilen abc på min lokala dator.
Hur man beräknar en binär diff på abc och abc2?
Applikationer:
-
Jag kunde bara skicka en
patch-fil (troligen max 100 MB) till den avlägsna servern istället för att ladda upp helaabc2-filen (det skulle ta några timmar igen!) och återskapaabc2på den avlägsna endast frånabcochpatch. -
Lokalt, istället för att slösa bort 8 GB för att säkerhetskopiera både
abcochabc2, kunde jag bara sparaabc+patch, så det tar < endast 4100 MB.
Hur gör man det?
PS: för text vet jag diff, men här letar jag efter något som kan fungera för alla råa binära format, det kan vara zip-filer eller körbara filer eller till och med andra typer av filer.
PS2: Om möjligt vill jag inte använda rsync; Jag vet att det kan replikera ändringar mellan två datorer på ett effektivt sätt (inte skicka data som inte har ändrats), men här vill jag verkligen ha en patch -fil, som kan reproduceras senare om Jag har både abc och patch.
Svar
För den andra applikationen / frågan skulle jag använda ett deduplicering av säkerhetskopieringsprogram som restic eller borgbackup, snarare än att försöka för att manuellt hålla reda på ”lappar” eller skillnader. restic säkerhetskopieringsprogrammet gör att du kan säkerhetskopiera kataloger från flera datorer till samma säkerhetskopia och deduplicera säkerhetskopieringsdata både bland fragment av filer från en enskild maskin och mellan en maskin. (Jag har ingen användarupplevelse med borgbackup, så jag kan inte säga något om det programmet.)
Beräkning och lagring av skillnaden mellan abc och abc2 filer kan göras med rsync.
Detta är ett exempel med abc och abc2 153 MB. Filen abc2 har ändrats genom att skriva över första 2,3 MB av filen med några andra data:
$ 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
Vi skapar lapp för att omvandla abc till abc2 och kalla det 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
Den genererade filen abc-diff är den faktiska diff (din ”patchfil”), medan abc-diff.sh ärett kort skalskript som rsync skapar åt dig:
$ cat abc-diff.sh rsync --read-batch=abc-diff ${1:-abc}
Detta skript ändrar abc så att det blir identiskt med abc2, med tanke på filen abc-diff:
$ md5sum abc abc2 be00efe0a7a7d3b793e70e466cbc53c6 abc 3decbde2d3a87f3d954ccee9d60f249b abc2 $ sh abc-diff.sh $ md5sum abc abc2 3decbde2d3a87f3d954ccee9d60f249b abc 3decbde2d3a87f3d954ccee9d60f249b abc2
Filen abc-diff kan nu överföras till vart du än har abc. Med kommandot rsync --read-batch=abc-diff abc applicerar du korrigeringsfilen på filen abc och förvandlar dess innehåll till samma som abc2 -fil på systemet där du skapade diff.
Återanvändning av plåstret en andra gång verkar säkert. Det finns inga felmeddelanden och inte heller ändras filens innehåll (kontrollsumman för MD5 ändras inte).
Observera att om du inte skapar en uttrycklig ”omvänd patch” finns det inget sätt att ångra applikationen av korrigeringsfilen.
Jag testade också att skriva 2,3 MB-modifieringen till någon annan plats i abc2 -data, lite längre in (vid cirka 50 MB) såväl som i början. Den genererade ”patch” var 4,6 MB stor, vilket tyder på att endast de modifierade bitarna lagrades i patch.
Kommentarer
Svar
Hur man beräknar en binär diff av abc och abc2?
Med bsdiff / bspatch eller xdelta och andra.
$ bsdiff older newer patch.bin # patch.bin is created [...] $ bspatch older newer patch.bin # newer is created
Dessa förmaningar från man-sidorna bör dock noteras:
-
bsdiffanvänder minne som är lika med 17 gånger storleken på oldfile , och kräver en absolut minsta arbetsuppsättningsstorlek på 8 gånger storleken på oldfile . -
bspatchanvänder minne som är lika med storleken på oldfile plus storleken på newfile , men tål en mycket liten arbetsuppsättning utan en dramatisk förlust av prestanda.
Kommentarer
- Kan du eventuellt visa ett exempel?
- Tack för ditt svar.
bsdiff uses memory equal to 17 times the size of oldfileså det här vinner ’ fungerar vanligtvis inte för 4 GB-filer (åtminstone på min 8 GB RAM-maskin). - @Basj Vad som är möjligt är att hugga upp 4 GB-filen i mindre (säg 128 MB vardera) och göra enskilda deltor. Detta kan läggas in i ett manus. chopped-bsdiff: hugga filerna, gör parvis bsdiffs, tjära upp dem i ett arkiv. chopped-bspatch: läs parvisa fläckar från arkivet, tillämpas på bitar av inmatningsfilen, catenate output.
- @Kaz ser jag, men jag ’ m mer ute ett färdigt verktyg som kan anropas på en rad (
mydiff abc abc2 > patchfileochmypatch abc patchfile > abc3) oavsett storlek. Om jag hackar i 128 MB bitar, vad händer om den första 1 GBabc== den sista (efterföljande) 1 GBabc2? När vi ’ jämförabc-first128mbmedabc2-first128mb, kommer ingen matchning att hittas, så det kanske inte är effektiv?
Svar
Har du försökt att bara tvinga diff för att behandla filerna som text:
diff -ua abc abc2
Som förklaras här .
-
-uutgång NUM (standard 3) rader i enhetligt sammanhang -
-abehandla alla filer som text
Detta skulle ge dig en korrigering. Nackdelen med detta är att ”raderna” kan vara ganska långa och det kan svälla plåstret. id = ”c166a34583”>
t vill faktiskt han. Jag ’ är intresserad av att veta om det fungerar som jag ’ jag är inte säker på hur länge ” rader ” kommer att vara.
abc och abc2. Sedan försökte jag diff -ua abc abc2 > patch, sedan kopierade jag abc till abc3 och jag försökte återhämta mig abc2 tack vare abc3 och patch: patch abc3 < patch, men det fungerade inte: i slutet var abc3 bara 1KB istället för 256 MB. Någon idé? 0x0a, dvs newline, eller mycket få, misstänker jag att den inte skulle ’ fungerar inte så bra, det skulle vara intressant att testa. wc -l som kommer att leta efter radbrytningar och enligt min erfarenhet går mycket snabbt. Jag förväntar mig att det på en godtycklig binär fungerar bra. Till exempel på min maskin hittade jag en 252M mp4 som hade 1,2 miljoner ” rader ” och en 59M .deb som hade cirka 230k, så ” rader ” på mindre än 220 byte respektive 258 byte. Jag förstår inte ’ varför dessa filer skulle vara så annorlunda än andra men du kan definitivt bli otur. I praktiken misstänker jag att det skulle fungera ganska bra och om inte så är det ’ fortfarande ett roligt hack. Svar
Använd xdelta , det skapades exakt för denna typ av användning. Baserat på VCDIFF (RFC 3284) i de senaste versionerna.
Kommentarer
- Länken fungerar inte (finns det en annan URL?). Kan du också lägga till ett exempel på några rader för att visa hur du: 1) beräknar diff
patch-filen och 2) återställerabc2, ges endastabcochpatch? - Tyvärr, fixad webbadress
- Tack @vonbrand . Skulle du ha ett sådant exempel?
Svar
Kompletterar andra svar enligt mina tester:
Med diff
skapade jag två mycket lika 256 MB-filer abc och abc2. Låt oss sedan skapa diff-filen:
diff -ua abc abc2 > abc-abc2.diff
Låt oss försöka återställa abc2 tack vare original abc fil och abc-abc2.diff:
cp abc abc3 patch abc3 < abc-abc2.diff
eller
cp abc abc3 patch abc3 -i abc-abc2.diff
eller
patch abc -i abc-abc2.diff -o abc3
Det fungerar på Linux. Jag försökte också på Windows (patch.exe och diff.exe finns också), men av okänd anledning misslyckades det: den producerade abc3 -filen är bara 1KB istället för 256MB (I ” Uppdaterar det här svaret senare här).
Med rsync
Som detaljerat i det accepterade svaret fungerar detta:
rsync --only-write-batch=abc-abc2-diff abc2 abc cp abc abc3 rsync --read-batch=abc-abc2-diff abc3
Med rdiff
Så detaljerat i detta svara , det här är också en lösning:
rdiff signature abc abc-signature rdiff delta abc-signature abc2 abc-abc2-delta rdiff patch abc abc-abc2-delta abc3
Testat också på Windows med rdiff.exe från här och det fungerar.
Kommentarer
- Jag ’ jag gissar att korrigeringen misslyckades i Windows eftersom den läste inmatningsfilen i ” text ” -läge som signalerar slutet på filen när den möter en KONTROLL -Z (byte 0x18) i inmatningsfilen. Detta är ett äldre läge från tidiga DOS-dagar då katalogen inte registrerade längden på filen och så beräknades fillängden baserat på antalet 512 byte sektorer. Om du kan säga till
patchatt öppna filen i binärt läge, bör den inte ’ inte ha detta fel.
rsync --read-batch=abc-diff ${1:-abc}(automatiskt genererat .sh-skript) gavremote destination is not allowed with --read-batchrsync error: syntax or usage error (code 1) at main.c(1326) [Receiver=3.1.2], menrsync --read-batch=abc-diff abcfungerade framgångsrikt.Vad är skillnaden mellan dessa två liknande kommandon?abcsom inmatning, applicera plåstretdiff-abcmed--read-batchmen ändrar inteabc” på plats ”, utan snarare mata ut till en ny filabc3? (om möjligt allt medrsync, utan piping, så att det fungerar enkelt på Linux såväl som Windows som också harrsync.exetillgängligt)$1hade ett värde.${1:-abc}betyder ” använd den första positionsparametern ($1) såvida det inte är ’ är tomt eller odefinierat. Om det ’ är tomt eller odefinierat, användabcistället ”. Jag ’ antar att$1hade ett värde när du försökte det, möjligen något som det tolkade som en fjärrmålsadress.${1:-abc}. Det misslyckades förmodligen beror på att jag försökte det på Windows (jag ’ m med rsync både på Linux för min avlägsna server och Windows lokalt). Men det är ’ perfekt eftersomrsync --read-batch=abc-diff abcfungerar 🙂