La oss si at jeg har en 4 GB fil abc
på meg lokal datamaskin. Jeg har lastet den opp til en fjern server via SFTP, det tok noen timer.
Nå har jeg endret filen litt (sannsynligvis maksimalt 50 MB, men ikke påfølgende byte i denne filen) lokalt, og lagret den i abc2
. Jeg beholdt også originalfilen abc
på min lokale datamaskin.
Hvordan beregne en binær diff på abc
og abc2
?
Programmer:
-
Jeg kunne bare sende en
patch
-fil (sannsynligvis maks 100 MB) til den fjerne serveren, i stedet for å laste opp heleabc2
-filen (det vil ta noen timer igjen!), og gjenskapeabc2
på den fjerne server fraabc
ogpatch
. -
Lokalt, i stedet for å kaste bort 8 GB for å sikkerhetskopiere både
abc
ogabc2
, kunne jeg bare lagreabc
+patch
, så det tar < bare 4100 MB.
Hvordan gjør jeg dette?
PS: for tekst, jeg vet diff
, men her ser jeg etter noe som kan fungere for ethvert rå binært format, det kan være zip-filer eller kjørbare filer eller til og med andre typer filer.
PS2: Hvis det er mulig, vil jeg ikke bruke rsync
; Jeg vet at det kan replikere endringer mellom to datamaskiner på en effektiv måte (ikke sende data som ikke er endret på nytt), men her vil jeg virkelig ha en patch
-fil, som kan reproduseres senere hvis Jeg har både abc
og patch
.
Svar
For det andre programmet / problemet vil jeg bruke et dedupliserende sikkerhetskopiprogram som restic
eller borgbackup
, i stedet for å prøve for å holde styr på «lapper» eller forskjeller manuelt. restic
sikkerhetskopiprogrammet lar deg sikkerhetskopiere kataloger fra flere maskiner til samme sikkerhetskopier, og deduplisere sikkerhetskopidataene blant fragmenter av filer fra en enkelt maskin så vel som mellom maskinen. (Jeg har ingen brukererfaring med borgbackup
, så jeg kan ikke si noe om det programmet.)
Beregning og lagring av en diff av abc
og abc2
filer kan gjøres med rsync
.
Dette er et eksempel med abc
og abc2
som 153 MB. Filen abc2
er endret ved å overskrive første 2,3 MB av filen med noen andre 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 lager lapp for å transformere abc
til abc2
og kall 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 genererte filen abc-diff
er den faktiske forskjellen («patch-filen»), mens abc-diff.sh
eret kort skallskript som rsync
oppretter for deg:
$ cat abc-diff.sh rsync --read-batch=abc-diff ${1:-abc}
Dette skriptet endrer abc
slik at det blir identisk med abc2
, gitt 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 nå overføres til andre steder du har abc
. Med kommandoen rsync --read-batch=abc-diff abc
vil du bruke oppdateringen på filen abc
, og forvandle innholdet til å være det samme som abc2
-filen på systemet der du opprettet diff.
Å bruke plasteret på nytt en gang til virker trygg. Det er ingen feilmeldinger, og innholdet på filen endres ikke (MD5-kontrollsummen endres ikke).
Merk at med mindre du oppretter en eksplisitt «omvendt oppdatering», er det ingen måte å angre applikasjonen enkelt av oppdateringen.
Jeg testet også å skrive 2,3 MB-modifikasjonen til et annet sted i abc2
-dataene, litt lenger inn (omtrent 50 MB), så vel som i begynnelsen. Den genererte «oppdateringen» var 4,6 MB stor, noe som tyder på at bare de modifiserte bitene ble lagret i oppdateringen.
Kommentarer
- Tusen takk @Kusalananda, det ‘ er flott! PS:
rsync --read-batch=abc-diff ${1:-abc}
(automatisk generert .sh-skript) garemote destination is not allowed with --read-batch
rsync error: syntax or usage error (code 1) at main.c(1326) [Receiver=3.1.2]
, menrsync --read-batch=abc-diff abc
fungerte vellykket.Hva er forskjellen mellom disse to like kommandoene? - 2/2 Er det en måte å ta
abc
som input, bruke patchdiff-abc
med--read-batch
men ikke modifiserabc
» på stedet «, men heller sende ut til en ny filabc3
? (hvis mulig alt medrsync
, uten rør, slik at det fungerer enkelt på Linux så vel som Windows som også harrsync.exe
tilgjengelig) - @Basj Kommandoene ville gjort forskjellige ting hvis
$1
hadde en verdi.${1:-abc}
betyr » bruk den første posisjonsparameteren ($1
) med mindre den ‘ er tom eller udefinert. Hvis det ‘ er tomt eller udefinert, bruker duabc
i stedet for «. Jeg ‘ antar at$1
hadde en verdi når du prøvde det, muligens noe den tolket som ekstern destinasjonsadresse. - @Basj I ‘ er ikke helt sikker på at dette er mulig, men jeg ‘ ll ta en titt i morgen etter søvn.
- Takk for svaret ditt om
${1:-abc}
. Det mislyktes sannsynligvis fordi jeg prøvde det på Windows (jeg ‘ m ved hjelp av rsync både på Linux for serveren min og Windows lokalt). Men det ‘ er perfekt sidenrsync --read-batch=abc-diff abc
fungerer 🙂
Svar
Hvordan beregner du en binær diff på abc og abc2?
Bruker bsdiff / bspatch eller xdelta og andre.
$ bsdiff older newer patch.bin # patch.bin is created [...] $ bspatch older newer patch.bin # newer is created
Imidlertid skal disse formaningene fra man-sidene bemerkes:
-
bsdiff
bruker minne som er lik 17 ganger størrelsen på oldfile , og krever en absolutt minimum arbeidsstørrelse på 8 ganger størrelsen på oldfile . -
bspatch
bruker minne som er lik størrelsen på oldfile pluss størrelsen på newfile , men tåler et veldig lite arbeidssett uten et dramatisk tap av ytelse.
Kommentarer
Svar
Har du prøvd å bare tvinge diff
for å behandle filene som tekst:
diff -ua abc abc2
Som forklart her .
-
-u
output NUM (standard 3) linjer i enhetlig kontekst -
-a
behandle alle filer som tekst
Dette skal gi deg en oppdatering. Ulempen med dette er at «linjene» kan være ganske lange, og det kan oppblåse plasteret.
Kommentarer
- Ups, ja du don ‘ t vil faktisk ha
n
. Jeg ‘ er interessert i å vite om det fungerer som jeg ‘ er usikker på hvor lenge » linjer » vil være. - Takk for kommentaren din! Jeg opprettet to veldig like 256 MB filer
abc
ogabc2
. Så prøvde jegdiff -ua abc abc2 > patch
, så kopierte jegabc
tilabc3
og jeg prøvde å gjenoppretteabc2
takket væreabc3
ogpatch
:patch abc3 < patch
, men det fungerte ikke: på slutten varabc3
bare 1KB i stedet for 256 MB. Noen ide? - Hmmm, ikke sikker på hva som skjedde. Jeg gjorde det bare på maskinen min, og det fungerte bedre enn jeg hadde forventet.Jeg tok en 382M fil som var tilfeldige heltall skrevet ut i binær fil til en fil. Jeg byttet 3 byte i den og gjorde diff og patch, og det fungerte. De resulterende filene var md5sum like.
- Hvis en stor fil ikke har byte
0x0a
, dvs. ny linje, eller veldig få, tror jeg at den ikke ville ‘ fungerer ikke så bra, det ville være interessant å teste. - Å helt sikkert. Du kan lage en utdannet gjetning på en binær med
wc -l
som vil se etter linjeskift og etter min erfaring kjører veldig raskt. Jeg forventer at det vil fungere ganske bra på en vilkårlig binær. For eksempel på maskinen min fant jeg en 252M mp4 som hadde 1,2 millioner » linjer «, og en 59M.deb
som hadde omtrent 230k, så gjennomsnitt » linjer » på henholdsvis mindre enn 220 byte og 258 byte. Jeg ser ikke ‘ hvorfor disse filene ville være så forskjellige enn andre, men du kan definitivt bli uheldig. I praksis mistenker jeg at det ville fungere ganske bra, og hvis ikke, er det ‘ fortsatt et morsomt hack.
Svar
Bruk xdelta , den ble opprettet nøyaktig for denne typen bruk. Basert på VCDIFF (RFC 3284) i de nyeste versjonene.
Kommentarer
- Koblingen fungerer ikke (er det en annen URL?). Kan du også legge til et eksempel på noen få linjer for å vise hvordan du: 1) beregner diff
patch
-filen, og 2) gjenoppretterabc2
, bare gittabc
ogpatch
? - Beklager, fast URL
- Takk @vonbrand . Vil du ha et slikt eksempel?
Svar
Utfyller andre svar i henhold til testene mine:
Med diff
opprettet jeg to veldig like 256 MB filer abc
og abc2
. La oss deretter opprette diff-filen:
diff -ua abc abc2 > abc-abc2.diff
La oss nå prøve å gjenopprette abc2
takket være original abc
fil og 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 fungerer på Linux. Jeg prøvde også på Windows (patch.exe og diff.exe er også tilgjengelig), men av en ukjent grunn mislyktes det: den produserte abc3
filen er bare 1KB i stedet for 256MB (I » Oppdater dette svaret senere her).
Med rsync
Som beskrevet i det aksepterte svaret, fungerer dette:
rsync --only-write-batch=abc-abc2-diff abc2 abc cp abc abc3 rsync --read-batch=abc-abc2-diff abc3
Med rdiff
Som beskrevet i dette svar , dette er også en løsning:
rdiff signature abc abc-signature rdiff delta abc-signature abc2 abc-abc2-delta rdiff patch abc abc-abc2-delta abc3
Testet også på Windows med rdiff.exe fra her og det fungerer.
Kommentarer
- Jeg ‘ jeg gjetter at oppdateringen mislyktes på Windows fordi den leste inndatafilen i » tekst » -modus som signaliserer slutten av filen når den møter en KONTROLL -Z (byte 0x18) i inndatafilen. Dette er en eldre modus fra tidlige DOS-dager da katalogen ikke registrerte lengden på filen og så ble fillengden beregnet basert på antall 512 byte sektorer. Hvis du kan fortelle
patch
om å åpne filen i binær modus, bør den ikke ‘ ikke ha denne feilen.
bsdiff uses memory equal to 17 times the size of oldfile
så dette vant ‘ t fungerer vanligvis ikke for 4 GB filer (i det minste på min 8 GB RAM-maskin).mydiff abc abc2 > patchfile
ogmypatch abc patchfile > abc3
) uansett størrelse. Også, hvis jeg hakker i 128 MB biter, hva skjer hvis den første 1 GBabc
== den siste (etterfølgende) 1 GBabc2
? Når vi ‘ sammenlignerabc-first128mb
medabc2-first128mb
, vil ingen treff bli funnet, så det kanskje ikke effektiv?