Il modo più veloce per elaborare dimensioni non compresse di file GZIPPED di grandi dimensioni


24

Una volta che un file è compresso con gzip, c'è un modo per interrogarlo rapidamente per dire qual è la dimensione del file non compresso (senza decomprimerlo), specialmente nei casi in cui il file non compresso ha dimensioni> 4 GB.

Secondo la RFC https://tools.ietf.org/html/rfc1952#page-5 è possibile eseguire una query sugli ultimi 4 byte del file, ma se il file non compresso era> 4 GB, il valore rappresenta solo il valoreuncompressed value modulo 2^32

Questo valore può anche essere recuperato eseguendo gunzip -l foo.gz, tuttavia la colonna "non compressa" contiene appena di uncompressed value modulo 2^32nuovo, presumibilmente mentre sta leggendo il piè di pagina come descritto sopra.

Mi stavo solo chiedendo se c'è un modo per ottenere la dimensione del file non compresso senza prima decomprimerlo, questo sarebbe particolarmente utile nel caso in cui i file compressi con gzip contengano 50 GB + di dati e richiederebbe un po 'di tempo per decomprimersi usando metodi come gzcat foo.gz | wc -c


EDIT: la limitazione di 4 GB è apertamente riconosciuta nella manpagina gzipdell'utilità inclusa con OSX ( Apple gzip 242)

  BUGS
    According to RFC 1952, the recorded file size is stored in a 32-bit
    integer, therefore, it can not represent files larger than 4GB. This
    limitation also applies to -l option of gzip utility.

2
+1 buona domanda! Ho il sospetto che la risposta sia no, che il formato dell'intestazione è stato progettato in un tempo prima che tali dimensioni dei file fossero anticipate. Pensandoci, gzipdeve essere più vecchio di molti utenti in questa community!
Celada,

2
gzipuscì nel 1992. Sarei sorpreso se ci fossero molti 23enni in roaming qui intorno. Sono sicuro che ce ne sono alcuni, ma da quello che posso dire l'età media è di circa 30-35.
Bratchley,

2
Potrebbe essere un buon momento per passare a xzquale non ha questa limitazione. GNU sta passando a xz.
Stéphane Chazelas,

@ StéphaneChazelas Interessante. Sfortunatamente i file che mi interessano sono al di fuori del mio controllo (cioè li riceviamo compressi), ma sembra xz che "risolverebbe" questo problema.
djhworld,

Risposte:


11

Credo che il modo più veloce sia quello di modificare in gzipmodo che il test in modalità dettagliata produca il numero di byte decompressi; sul mio sistema, con un file di 7761108684 byte, ottengo

% time gzip -tv test.gz
test.gz:     OK (7761108684 bytes)
gzip -tv test.gz  44.19s user 0.79s system 100% cpu 44.919 total

% time zcat test.gz| wc -c
7761108684
zcat test.gz  45.51s user 1.54s system 100% cpu 46.987 total
wc -c  0.09s user 1.46s system 3% cpu 46.987 total

Per modificare gzip (1.6, come disponibile in Debian), la patch è la seguente:

--- a/gzip.c
+++ b/gzip.c
@@ -61,6 +61,7 @@
 #include <stdbool.h>
 #include <sys/stat.h>
 #include <errno.h>
+#include <inttypes.h>

 #include "closein.h"
 #include "tailor.h"
@@ -694,7 +695,7 @@

     if (verbose) {
         if (test) {
-            fprintf(stderr, " OK\n");
+            fprintf(stderr, " OK (%jd bytes)\n", (intmax_t) bytes_out);

         } else if (!decompress) {
             display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
@@ -901,7 +902,7 @@
     /* Display statistics */
     if(verbose) {
         if (test) {
-            fprintf(stderr, " OK");
+            fprintf(stderr, " OK (%jd bytes)", (intmax_t) bytes_out);
         } else if (decompress) {
             display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
         } else {

Costruisce ancora internamente i dati effettivi o è -tgià ottimizzato al riguardo? Il miglioramento è abbastanza piccolo da far sembrare che tu abbia risparmiato solo il tempo di uscita.
frostschutz,

Sì, deve decomprimere tutto per capire la dimensione originale ... Quindi questo sta solo facendo risparmiare tempo di output, ma penso che sia tutto ciò che può essere salvato.
Stephen Kitt,

Interessante, sì, stavo pensando che avresti bisogno di cambiare il codice per farlo funzionare davvero. Sfortunatamente nel mio caso i file che mi interessano non sono effettivamente sotto il mio controllo, li ricevo da una parte esterna, quindi non sarei in grado di comprimerli in primo luogo. Penso che l'unico modo per supportare completamente i file> 4 GB sarebbe patch gzip per avere un footer da 12 byte, 4 byte per CRC e 8 byte (64 bit) per le dimensioni del file. Tuttavia, ciò romperebbe la retrocompatibilità con i gzips esistenti!
djhworld,

La soluzione che do sopra non comporta la compressione iniziale dei file, anche se sono in esecuzione gzip; Corro solo gzipsui file compressi, che non li ricomprime, li verifica semplicemente. (La patch è una prova di concetto veloce e sporca, ha bisogno di qualche altra modifica con cui lavorare gunzip.)
Stephen Kitt,

@StephenKitt Ah interessante! Un trucco ancora migliore / più sporco sarebbe quello di incorporare quei dati nel FCOMMENTcampo. In questo modo gli utenti possono eseguire una query su un intervallo di byte per recuperare tali dati. Questo sarebbe utile nel mio caso, in particolare per gli articoli archiviati in Amazon S3
djhworld

0

Se avete bisogno le dimensioni di un file compresso o insieme di file, la soluzione migliore è quella di utilizzare tar -zo tar -jinvece gzipcome tarinclude la dimensione dei file non compressi. Utilizzare lesspipeper dare un'occhiata all'elenco dei file:

aptitude install lesspipe
lesspipe <compressed file> | less

Se lessè configurato per l'uso lesspipe:

less <compressed file>

Ricorda che può volerci molto tempo. Tuttavia, il sistema rimane reattivo, il che consente di interrompere il processo di decompressione.

Un altro approccio sarebbe quello di registrare il rapporto compresso e interrogare invece quel file [testo]:

gzip --verbose file 2>&1 | tee file.gz.log
file:    64.5% -- replaced with file.gz

Richiede il calcolo per trovare la dimensione del file reale però.

Potresti anche fare lo stesso con tar, che è in realtà quello che faccio con backup di grandi dimensioni in quanto impedisce di eseguire l'intero processo di decompressione per ottenere solo una dimensione o un nome di file, ad esempio.


2
Tar.gz non deve essere decompresso completamente anche per ottenere l'elenco di tutti i file?
frostschutz,

In effetti deve essere. Questo è l'unico modo che mi viene in mente per ottenere la dimensione del file non compresso. Con tarte hai le dimensioni del file originale registrate nell'archivio. Non sono sicuro che zipsi comporti diversamente, d'altra parte.

1
A quel punto l'OP potrebbe anche eseguire il wc -ccomando.
Bratchley,

@Bratchley ovviamente. Ma ci vorrebbe molto tempo per ottenere tutti i risultati. Da qui i miei due suggerimenti per registrare le dimensioni dei file.

0

Che dire

gzip -l file.gz|tail -n1|awk '{print $2}'

numfmt --to=iec $(gzip -l file.gz|tail -n1|awk '{print $2}')

1
Ciò non funziona per file di grandi dimensioni, come spiegato dall'OP.
Stephen Kitt,

-2
gunzip -c $file | wc -c

Questo richiederà molto tempo, ma ti darà la dimensione finale in byte.


5
Questo è esattamente ciò che l'OP sta cercando di evitare di dover fare.
depquid
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.