Schnellste Methode zum Ermitteln der unkomprimierten Größe einer großen GZIPPED-Datei

24

Wenn eine Datei komprimiert ist, können Sie sie schnell abfragen, um die Größe der nicht komprimierten Datei zu bestimmen (ohne sie zu dekomprimieren), insbesondere in Fällen, in denen die Größe der nicht komprimierten Datei> 4 GB ist.

Laut dem RFC https://tools.ietf.org/html/rfc1952#page-5 können Sie die letzten 4 Bytes der Datei abfragen, aber wenn die unkomprimierte Datei> 4 GB war, dann stellt der Wert nur das daruncompressed value modulo 2^32

Dieser Wert kann auch durch Ausführen gunzip -l foo.gzdes Befehls abgerufen werden. Die Spalte "unkomprimiert" enthält jedoch nur einen neuen Wert uncompressed value modulo 2^32, vermutlich, wenn die Fußzeile wie oben beschrieben gelesen wird.

Ich habe mich nur gefragt, ob es eine Möglichkeit gibt, die unkomprimierte Dateigröße zu ermitteln, ohne sie zuerst dekomprimieren zu müssen. Dies ist besonders nützlich, wenn komprimierte Dateien mehr als 50 GB Daten enthalten und die Dekomprimierung mit Methoden wie gzcat foo.gz | wc -c


BEARBEITEN: Die Beschränkung von 4 GB wird auf der manSeite des in gzipOSX ( Apple gzip 242) enthaltenen Dienstprogramms offen anerkannt.

  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.
djhworld
quelle
2
+1 gute Frage! Ich vermute, die Antwort ist nein, das Header-Format wurde in einer Zeit entwickelt, bevor solche Dateigrößen erwartet wurden. Denken Sie darüber nach, gzipmuss älter sein als viele Benutzer in dieser Community!
Celada,
2
gzipIch wäre überrascht, wenn hier viele 23-Jährige herumlaufen würden. Ich bin sicher, dass es einige gibt, aber nach dem, was ich sagen kann, liegt das Durchschnittsalter zwischen 30 und 35 Jahren.
Bratchley
2
Eine gute Zeit, um zu wechseln, xzdie diese Einschränkung nicht hat. GNU wechselt zu xz.
Stéphane Chazelas
@ StéphaneChazelas Interessant. Leider liegen die Dateien, an denen ich interessiert bin, außerhalb meiner Kontrolle (dh wir erhalten sie komprimiert), aber es sieht auf jeden xz Fall so aus, als würde dieses Problem gelöst.
Djhworld

Antworten:

11

Ich glaube, der schnellste Weg ist zu ändern, gzipso dass das Testen im ausführlichen Modus die Anzahl der dekomprimierten Bytes ausgibt; Auf meinem System erhalte ich mit einer 7761108684-Byte-Datei

% 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

Um gzip (1.6, wie in Debian verfügbar) zu ändern, ist der Patch wie folgt:

--- 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 {
Stephen Kitt
quelle
Baut es die eigentlichen Daten noch intern auf oder ist -tes diesbezüglich bereits optimiert? Die Verbesserung ist klein genug, um den Eindruck zu erwecken, dass Sie nur die Ausgabezeit gespart haben.
Frostschutz
Ja, es muss alles dekomprimiert werden, um die ursprüngliche Größe herauszufinden ... Das spart also nur die Ausgabezeit, aber ich denke, das ist alles, was gespart werden kann.
Stephen Kitt
Interessant, ja, ich dachte, Sie müssten den Code ändern, damit dies tatsächlich funktioniert. In meinem Fall liegen die Dateien, die mich interessieren, leider nicht in meiner Kontrolle. Ich erhalte sie von einer externen Partei und kann sie daher erst gar nicht komprimieren. Ich denke, die einzige Möglichkeit zur vollständigen Unterstützung von> 4 GB-Dateien wäre das Patchen von gzip mit einer 12-Byte-Fußzeile, 4 Byte für CRC und 8 Byte (64 Bit) für die Dateigröße. Dies würde jedoch die Abwärtskompatibilität mit vorhandenen gzips aufheben!
Djhworld
Bei der oben genannten Lösung werden die Dateien zunächst nicht komprimiert, obwohl sie ausgeführt werden gzip. Ich starte nur gzipdie komprimierten Dateien, die nicht erneut komprimiert werden, sondern nur überprüft werden. (Der Patch ist ein schneller und unsauberer Proof-of-Concept, für die Arbeit sind noch einige Änderungen erforderlich gunzip.)
Stephen Kitt,
@ StephenKitt Ah interessant! Ein noch besserer / schmutzigerer Hack wäre es, diese Daten in das FCOMMENTFeld einzubetten . Auf diese Weise können Benutzer einen Byte-Bereich abfragen, um diese Daten abzurufen. Dies wäre in meinem Fall nützlich, insbesondere für Artikel, die in Amazon S3
djhworld
0

Wenn Sie die Größe einer komprimierten Datei oder Gruppe von Dateien benötigen, die beste Wahl zu verwenden ist tar -zoder tar -jstatt gzipwie tarbeinhaltet die unkomprimierte Dateien Größe. Hier können Sie lesspipedie Liste der Dateien einsehen:

aptitude install lesspipe
lesspipe <compressed file> | less

Wenn lesskonfiguriert ist zu verwenden lesspipe:

less <compressed file>

Bedenken Sie jedoch, dass dies sehr lange dauern kann. Ihr System reagiert jedoch weiterhin, sodass Sie den Dekomprimierungsprozess beenden können.

Ein anderer Ansatz wäre, das komprimierte Verhältnis zu protokollieren und stattdessen diese [Text] -Datei abzufragen:

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

Es ist jedoch eine Berechnung erforderlich, um die tatsächliche Dateigröße zu ermitteln.

Sie können auch das Gleiche tun tar, was ich auch mit großen Backups mache, da dies verhindert, dass der gesamte Dekomprimierungsprozess ausgeführt wird, um beispielsweise nur eine Dateigröße oder einen Dateinamen zu erhalten.


quelle
2
Muss tar.gz nicht auch vollständig dekomprimiert werden, um eine Liste aller Dateien zu erhalten?
Frostschutz
In der Tat muss es sein. Nur so kann ich mir vorstellen, die unkomprimierte Dateigröße zu ermitteln. Mit haben tarSie die ursprüngliche Dateigröße im Archiv protokolliert. Ich bin mir nicht sicher zip, ob ich mich anders verhalte.
1
An diesem Punkt könnte das OP genauso gut den wc -cBefehl ausführen.
Bratchley
@ Bratchley natürlich. Es würde jedoch viel Zeit in Anspruch nehmen, um alle Ergebnisse zu erzielen. Daher meine beiden Vorschläge, um Dateigrößen zu protokollieren.
0

Wie wäre es mit

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

numfmt --to=iec $(gzip -l file.gz|tail -n1|awk '{print $2}')
Syco
quelle
1
Dies funktioniert nicht für große Dateien, wie vom OP erläutert.
Stephen Kitt
-2
gunzip -c $file | wc -c

Dies dauert sehr lange, gibt Ihnen jedoch die endgültige Größe in Byte.

Nick
quelle
5
Genau dies versucht das OP zu vermeiden.
Depquid