2009-02-25 8 views
16

Sembra che questo non sia una cosa deterministica o esiste un modo per farlo in modo affidabile?Esiste un modo sicuro per eseguire un diff su due file compressi?

+1

Cosa desideri un diff? L'elenco dei file (FileA esiste in uno ma non nell'altro). Il contenuto dei file (FileB nel primo zip ha queste modifiche rispetto al FileB nel secondo zip). O tutto quanto sopra? La risposta di eduffy potrebbe funzionare (in Linux) se non ti interessa il contenuto. – JMD

+0

Inoltre, quale piattaforma? Windows, Linux, altro? – JMD

+0

Se ti interessa solo se i file compressi sono uguali allora perché non confrontare gli hash? – EBGreen

risposta

7

Affidabile: decomprimere entrambi, diff.

Non ho idea se la risposta è abbastanza buona per il vostro uso, ma funziona.

+0

Sto cercando di evitare l'apertura, l'espansione e la diffusione, potrebbe essere più costoso. – ApplePieIsGood

+0

Sfortunatamente, è l'unico modo affidabile per farlo. – Powerlord

+1

@Powerlord: per curiosità la risposta di eduffy è inaffidabile? O solo più tardi del tuo commento? – orangepips

29

Se stai usando gzip, si può fare qualcosa di simile:

# diff <(zcat file1.gz) <(zcat file2.gz) 
+0

Beh, ho bisogno di farlo a livello di programmazione, e non sto correndo in un ambiente unix (sfortunatamente). – ApplePieIsGood

+5

in che modo la soluzione in questa risposta non risolve "programmaticamente" il problema? – hop

+6

Questo è bello sapere (non ho mai saputo che potevi canalizzare in due programmi su un altro programma senza creare file temporanei.) Ero confuso e incappato in bug, fino a quando non ho capito che ** non può avere uno spazio tra i < e il paren. ** –

1

Beyond compare non ha alcun problema con questo.

+0

Mi chiedo se lo espanderanno dietro le quinte e diff? Questa è la cosa, difficile da dire con un'app che cosa fa. – ApplePieIsGood

+0

Sono abbastanza sicuro che si espandono dietro le quinte. Devono essere in grado di mostrare una copia affiancata di due file dagli archivi zip. –

+0

È proprietario, quindi chissà cosa fa? –

12

Beh, immagino che lo zdiff sia utile.

+0

il collegamento va a un sito chiamato 'Come reindirizzare l'output del comando in un file 'si prega di essere abbastanza gentile da aggiornare il link –

5

In generale, non si può evitare di decompressione e quindi confrontando. Diversi compressori genereranno flussi di byte DEFLATEd diversi, che quando INFLATEd generano lo stesso testo originale. Non puoi semplicemente confrontare i dati DEFLATEd, uno con l'altro. Ciò fallirà in alcuni casi.

Ma in uno scenario ZIP, è presente un CRC32 calcolato e memorizzato per ciascuna voce. Quindi, se si desidera controllare i file, è sufficiente confrontare il CRC32 memorizzato associato a ciascun flusso DEFLATEd, con le avvertenze sulle proprietà di unicità dell'hash CRC32. Potrebbe adattarsi alle tue esigenze per confrontare FileName e CRC.

Avresti bisogno di una libreria ZIP che legge i file zip e espone quelle cose come proprietà sull'oggetto "ZipEntry". DotNetZip lo farà per le app .NET.

2

Questo non è particolarmente elegante, ma è possibile utilizzare l'applicazione FileMerge fornita con gli strumenti di sviluppo Mac OS X per confrontare il contenuto dei file zip utilizzando un filtro personalizzato.

creare uno script ~/bin/zip_filemerge_filter.bash con contenuti:

#!/bin/bash 
## 
# List the size, CR-32 checksum, and file path of each file in a zip archive, 
# sorted in order by file path. 
## 
unzip -v -l "${1}" | cut -c 1-9,59-,49-57 | sort -k3 
exit $? 

Fai lo script eseguibile (chmod +x ~/bin/zip_filemerge_filter.bash).

Apri FileMerge, apri le Preferenze e vai alla scheda "Filtri". Aggiungi un elemento alla lista con: Estensione: "zip", Filtro: "~/bin/zip_filemerge_filter.bash $ (FILE)", Visualizza: Filtrato, Applica *: No. (Ho anche aggiunto il filer per. jar e file .war.)

Quindi utilizzare FileMerge (o il wrapper "opendiff" della riga di comando) per confrontare due file .zip.

Questo non ti consente di diffare il contenuto dei file all'interno degli archivi zip, ma ti permetterà di vedere rapidamente quali file appaiono all'interno di un unico archivio e quali file esistono in entrambi ma hanno contenuti diversi (cioè dimensioni e/o checksum).

1

In realtà gzip e bzip2 sono entrambi dotati di strumenti dedicati per farlo.

con gzip:

$ zdiff file1.gz file2.gz 

Con bzip2:

$ bzdiff file1.bz2 file2.bz2 

Ma tenere a mente che per i file di grandi dimensioni, si potrebbe incorrere in problemi di memoria (I originariamente venuto qui per scoprire come per risolverli, quindi non ho ancora la risposta).

0

ho trovato sollievo con questo semplice script Perl: diffzips.pl

E diff ricorsivamente tutti i file zip all'interno della zip originale, che è particolarmente utile per i diversi formati di pacchetti Java: vaso, la guerra, e l'orecchio.

zipcmp utilizza un approccio più semplice e non ricorre alle cerniere archiviate.

3

zipcmp confronta gli archivi zip zip1 e zip2 e controlla se contengono gli stessi file, confrontando i loro nomi, dimensioni non compresse e CRC. L'ordine dei file e le differenze di dimensioni compresse vengono ignorati.

sudo apt-get install zipcmp

+0

Potresti spiegarmi l'output restituito eseguendo' zipcmp' Ho ottenuto una riga di introduzione come '- 2380 d0c49aea c5-custom-prodotto-5.2.0/WSO2/runtime2/bin/bootstrap/logging.properties'. So che '-' indica il file zip resavant ma ciò che è indicato da' 2380' e 'd0c49aea'. Grazie –

+0

"2380" = zip di accesso; "d0c49aea" è md5 di entrata; nome della voce "c5-custom-product-5.2.0/wso2/runtime2/bin/bootstrap/logging.properties". Guarda md5, la voce può avere le stesse dimensioni ma contenuti diversi – Wender

0

Generalmente uso un approccio come @ mrabbit di ma corro 2 comandi decomprimere e diff dell'uscita come richiesto. Ad esempio ho bisogno di confrontare 2 file Java WAR.

$ sdiff --width 160 \ 
    <(unzip -l -v my_num1.war | cut -c 1-9,59-,49-57 | sort -k3) \ 
    <(unzip -l -v my_num2.war | cut -c 1-9,59-,49-57 | sort -k3) 

Con conseguente uscita in questo modo:

--------   -------              --------   ------- 
Archive:                  Archive: 
-------- -------- ----               -------- -------- ---- 
48619281   130 files             | 51043693   130 files 
    1116 060ccc56 index.jsp               1116 060ccc56 index.jsp 
     0 00000000 META-INF/               0 00000000 META-INF/ 
    155 b50f41aa META-INF/MANIFEST.MF          |  155 701f1623 META-INF/MANIFEST.MF 
Length CRC-32 Name               Length CRC-32 Name 
    1179 b42096f1 version.jsp              1179 b42096f1 version.jsp 
     0 00000000 WEB-INF/                0 00000000 WEB-INF/ 
     0 00000000 WEB-INF/classes/              0 00000000 WEB-INF/classes/ 
     0 00000000 WEB-INF/classes/com/             0 00000000 WEB-INF/classes/com/ 
... 
... 
1

Una soluzione di pitone per i file zip:

import difflib 
import zipfile 

def diff(filename1, filename2): 
    differs = False 

    z1 = zipfile.ZipFile(open(filename1)) 
    z2 = zipfile.ZipFile(open(filename2)) 
    if len(z1.infolist()) != len(z2.infolist()): 
     print "number of archive elements differ: {} in {} vs {} in {}".format(
      len(z1.infolist()), z1.filename, len(z2.infolist()), z2.filename) 
     return 1 
    for zipentry in z1.infolist(): 
     if zipentry.filename not in z2.namelist(): 
      print "no file named {} found in {}".format(zipentry.filename, 
                 z2.filename) 
      differs = True 
     else: 
      diff = difflib.ndiff(z1.open(zipentry.filename), 
           z2.open(zipentry.filename)) 
      delta = ''.join(x[2:] for x in diff 
          if x.startswith('- ') or x.startswith('+ ')) 
      if delta: 
       differs = True 
       print "content for {} differs:\n{}".format(
        zipentry.filename, delta) 
    if not differs: 
     print "all files are the same" 
     return 0 
    return 1 

Usa come

diff(filename1, filename2) 

Esso mette a confronto i file per linea linea in memoria e mostra i cambiamenti.