Forskel på to lignende store rå binære filer

Lad os sige, at jeg har en 4 GB-fil abc på min lokal computer. Jeg har uploadet den til en fjern server via SFTP, det tog et par timer.

Nu har jeg lidt ændret filen (sandsynligvis maksimalt 50 MB, men ikke på hinanden følgende byte i denne fil) lokalt, og gemte det i abc2. Jeg gemte også den originale fil abc på min lokale computer.

Sådan beregnes en binær diff på abc og abc2?

Applikationer:

  • Jeg kunne kun sende en patch -fil (sandsynligvis maks. 100 MB) til den fjerne server i stedet for at geninstallere hele abc2 filen (det ville tage et par timer igen!), og genskab abc2 på den fjerne server kun fra abc og patch.

  • Lokalt, i stedet for at spilde 8 GB til backup af både abc og abc2, kunne jeg kun gemme abc + patch, så det tager kun < 4100 MB.

Hvordan gør man det?

PS: for tekst kender jeg diff, men her leder jeg efter noget, der kunne fungere for ethvert rå binært format, det kunne være zip-filer eller eksekverbare filer eller endda andre filtyper.

PS2: Hvis det er muligt, vil jeg ikke bruge rsync; Jeg ved, at det kan replikere ændringer mellem 2 computere på en effektiv måde (ikke videresende data, der ikke er ændret), men her vil jeg virkelig have en patch -fil, der kan reproduceres senere, hvis Jeg har både abc og patch.

Svar

Til det andet program / problem vil jeg bruge et deduplicering af sikkerhedskopieringsprogram som restic eller borgbackup i stedet for at prøve for manuelt at holde styr på “patches” eller diffs. restic sikkerhedskopieringsprogrammet giver dig mulighed for at sikkerhedskopiere mapper fra flere maskiner til det samme sikkerhedskopier og deduplicere sikkerhedskopidataene blandt fragmenter af filer fra en enkelt maskine såvel som mellem maskinen. (Jeg har ingen brugeroplevelse med borgbackup, så jeg kan ikke sige noget om dette program.)

Beregning og lagring af en diff af abc og abc2 filer kan gøres med rsync.

Dette er et eksempel med abc og abc2 153 MB. Filen abc2 er blevet ændret ved at overskrive første 2,3 MB af filen med nogle 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 opretter ud patch til at omdanne abc til abc2 og kalde 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 genererede fil abc-diff er den faktiske diff (din “patch-fil”), mens abc-diff.sh eret kort shell-script, som rsync opretter til dig:

 $ cat abc-diff.sh rsync --read-batch=abc-diff ${1:-abc}  

Dette script ændrer abc, så det bliver identisk med abc2, givet filen abc-diff:

 $ md5sum abc abc2 be00efe0a7a7d3b793e70e466cbc53c6 abc 3decbde2d3a87f3d954ccee9d60f249b abc2 $ sh abc-diff.sh $ md5sum abc abc2 3decbde2d3a87f3d954ccee9d60f249b abc 3decbde2d3a87f3d954ccee9d60f249b abc2  

Filen abc-diff kunne nu overføres til hvor som helst du har abc. Med kommandoen rsync --read-batch=abc-diff abc anvender du patch til filen abc og omdanner dens indhold til at være det samme som abc2 -fil på det system, hvor du oprettede diff.

Genanvendelse af programrettelsen en anden gang virker sikkert. Der er ingen fejlmeddelelser, og heller ikke ændres filens indhold (MD5-kontrolsummen ændres ikke.).

Bemærk, at medmindre du opretter en eksplicit “omvendt patch”, er der ingen måde at fortryde applikationen let af plasteret.


Jeg testede også at skrive 2,3 MB-modifikationen til et andet sted i abc2 -dataene lidt længere inde (ca. 50 MB) såvel som i starten. Den genererede “patch” var 4,6 MB stor, hvilket antyder, at kun de modificerede bits blev gemt i patchen.

Kommentarer

  • Mange tak @Kusalananda, det ‘ er fantastisk! PS: rsync --read-batch=abc-diff ${1:-abc} (automatisk genereret .sh-script) gav remote destination is not allowed with --read-batch rsync error: syntax or usage error (code 1) at main.c(1326) [Receiver=3.1.2], men rsync --read-batch=abc-diff abc fungerede med succes.Hvad er forskellen mellem disse to lignende kommandoer?
  • 2/2 Er der en måde at tage abc som input, anvende patch diff-abc med --read-batch men ændrer ikke abc ” på stedet “, men snarere output til en ny fil abc3? (hvis muligt alle med rsync uden rør, så det fungerer let på Linux såvel som Windows, som også har rsync.exe tilgængelig)
  • @Basj Kommandoerne ville gøre forskellige ting, hvis $1 havde en værdi. ${1:-abc} betyder ” brug den første positionsparameter ($1), medmindre den ‘ er tom eller udefineret. Hvis det ‘ er tomt eller udefineret, skal du bruge abc i stedet for “. Jeg ‘ antager, at $1 havde en værdi, da du prøvede det, muligvis noget, det fortolkes som en ekstern destinationsadresse.
  • @Basj I ‘ Jeg er ikke helt sikker på, at dette er muligt, men jeg ‘ ll kig i morgen efter søvn.
  • Tak for dit svar om ${1:-abc}. Det mislykkedes sandsynligvis, fordi jeg prøvede det på Windows (jeg ‘ m ved hjælp af rsync både på Linux til min fjerne server og Windows lokalt). Men det er ‘ perfekt, da rsync --read-batch=abc-diff abc fungerer 🙂

Svar

Hvordan beregnes en binær diff af abc og abc2?

Brug af bsdiff / bspatch eller xdelta og andre.

$ bsdiff older newer patch.bin # patch.bin is created [...] $ bspatch older newer patch.bin # newer is created 

Disse advarsler fra mandsiderne skal dog bemærkes:

  • bsdiff bruger hukommelse svarende til 17 gange størrelsen på oldfile , og kræver en absolut minimumsstørrelse på arbejdssættet på 8 gange størrelsen på oldfile .
  • bspatch bruger hukommelse svarende til størrelsen på oldfile plus størrelsen på newfile , men tåler et meget lille arbejdssæt uden et dramatisk tab af ydeevne.

Kommentarer

  • Kunne du muligvis vise et eksempel?
  • Tak for dit svar. bsdiff uses memory equal to 17 times the size of oldfile så dette vinder ‘ fungerer normalt ikke til 4 GB filer (i det mindste på min 8 GB RAM-maskine).
  • @Basj Hvad der er muligt er at hugge 4GB-filen op i mindre filer (f.eks. 128MB hver) og lave individuelle deltaer. Dette kunne pakkes ind i et script. hakket-bsdiff: hugg filerne, gør parvise bsdiffer, tar dem op i et arkiv. chopped-bspatch: læs parvise programrettelser fra arkivet, anvend på klumper af inputfil, sammenkæd output.
  • @Kaz ser jeg, men jeg ‘ m mere på udkig efter et brugervenligt værktøj, der kan kaldes på 1 linje (mydiff abc abc2 > patchfile og mypatch abc patchfile > abc3) uanset størrelse. Også, hvis jeg hugger i 128 MB stykker, hvad sker der hvis den første 1 GB abc == den sidste (efterfølgende) 1 GB abc2 ? Når vi ‘ sammenligner abc-first128mb med abc2-first128mb, findes der ingen match, så det måske ikke effektiv?

Svar

Har du prøvet bare at tvinge diff for at behandle filerne som tekst:

diff -ua abc abc2 

Som forklaret her .

  • -u output NUM (standard 3) linjer i en samlet kontekst
  • -a behandle alle filer som tekst

Dette skal give dig en patch. Ulempen ved dette er, at “linjerne” kan være ret lange, og det kan svulme plasteret op.

Kommentarer

  • Ups, ja du don ‘ t vil faktisk have n. Jeg ‘ er interesseret i at vide, om det fungerer, da jeg ‘ er ikke sikker på, hvor længe ” linjer ” vil være.
  • Tak for din kommentar! Jeg oprettede to meget ens 256 MB filer abc og abc2. Så prøvede jeg diff -ua abc abc2 > patch, så kopierede jeg abc til abc3 og jeg forsøgte at komme mig abc2 takket være abc3 og patch: patch abc3 < patch, men det fungerede ikke: i slutningen var abc3 kun 1 KB i stedet for 256 MB. Har du nogen idé?
  • Hmmm, ved ikke hvad der skete. Jeg gjorde det bare på min maskine, og det fungerede bedre, end jeg havde forventet.Jeg tog en 382M-fil, der var tilfældige heltal skrevet ud i binær til en fil. Jeg ændrede 3 byte i det og gjorde diff og patch, og det fungerede. De resulterende filer var md5sum lige.
  • Hvis en stor fil ikke har nogen byte 0x0a, dvs. newline eller meget få, formoder jeg, at den ikke ville ‘ fungerer ikke så godt, det ville være interessant at teste.
  • Åh helt sikkert. Du kan lave et veluddannet gæt på en binær med wc -l som vil kigge efter linjeskift og efter min erfaring kører meget hurtigt. Jeg forventer på en vilkårlig binær, at det fungerer ret godt. For eksempel på min maskine fandt jeg en 252M mp4, der havde 1,2 millioner ” linjer “, og en 59M .deb, der havde ca. 230k, så gennemsnit ” linjer ” på henholdsvis mindre end 220 bytes og 258 bytes. Jeg kan ikke ‘ ikke se, hvorfor disse filer ville være så forskellige end andre, men du kunne helt sikkert blive uheldig. I praksis formoder jeg, at det ville fungere ret godt, og hvis ikke, er det ‘ stadig et sjovt hack.

Svar

Brug xdelta , det blev oprettet nøjagtigt til denne type anvendelser. Baseret på VCDIFF (RFC 3284) i de nyeste versioner.

Kommentarer

  • Linket fungerer ikke (er der en anden URL?). Kan du også tilføje et eksempel på nogle få linjer for at vise, hvordan du: 1) beregner diff patch -filen, og 2) gendanner abc2 , kun givet abc og patch?
  • Beklager, fast URL
  • Tak @vonbrand . Vil du have et sådant eksempel?

Svar

Supplerer til andre svar i henhold til mine tests:

Med diff

oprettede jeg to meget ens 256 MB filer abc og abc2. Lad os derefter oprette diff-filen:

diff -ua abc abc2 > abc-abc2.diff 

Lad os nu prøve at gendanne 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øvede også på Windows (patch.exe og diff.exe er også tilgængelige), men af en ukendt årsag mislykkedes det: den producerede abc3 -fil er kun 1 KB i stedet for 256 MB (I ” Opdater dette svar senere her).

Med rsync

Som beskrevet i det accepterede svar 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 gætter på patch mislykkedes på Windows, fordi den læste inputfilen i ” tekst ” -tilstand, der signalerer slutningen af filen, når den støder på en KONTROL -Z (byte 0x18) i inputfilen. Dette er en ældre tilstand fra tidlige DOS-dage, hvor biblioteket ikke registrerede længden på filen, og så blev fillængden beregnet ud fra antallet af 512 byte sektorer. Hvis du kan fortælle patch at åbne filen i binær tilstand, skal den ikke ‘ ikke have denne fejl.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *