Schnelle Verkettung mehrerer GZip-Dateien

87

Ich habe eine Liste von gzip-Dateien:

file1.gz
file2.gz
file3.gz

Gibt es eine Möglichkeit, diese Dateien zu verketten oder in eine gzip-Datei zu komprimieren, ohne sie dekomprimieren zu müssen?

In der Praxis werden wir dies in einer Webdatenbank (CGI) verwenden. Wo das Web eine Abfrage vom Benutzer empfängt und alle auf der Abfrage basierenden Dateien auflistet und sie dem Benutzer in einer Batchdatei wiedergibt.

neversaint
quelle

Antworten:

101

Mit gzip-Dateien können Sie die Dateien einfach wie folgt miteinander verketten:

cat file1.gz file2.gz file3.gz > allfiles.gz

Gemäß dem gzip RFC ,

Eine gzip-Datei besteht aus einer Reihe von "Mitgliedern" (komprimierten Datensätzen). [...] Die Mitglieder erscheinen einfach nacheinander in der Datei, ohne zusätzliche Informationen vor, zwischen oder nach ihnen.

Beachten Sie, dass dies nicht genau mit dem Erstellen einer einzelnen gzip-Datei der verketteten Daten identisch ist. Unter anderem bleiben alle ursprünglichen Dateinamen erhalten. Gunzip scheint dies jedoch als Äquivalent zu einer Verkettung zu behandeln.

Da vorhandene Tools die Dateinamen-Header für die zusätzlichen Mitglieder im Allgemeinen ignorieren, ist es nicht einfach, einzelne Dateien aus dem Ergebnis zu extrahieren. Wenn dies möglich sein soll, erstellen Sie stattdessen eine ZIP-Datei. ZIP und GZIP verwenden beide den DEFLATE-Algorithmus für die eigentliche Komprimierung (ZIP unterstützt einige andere Komprimierungsalgorithmen sowie eine Option - Methode 8 entspricht der GZIP-Komprimierung). Der Unterschied liegt im Metadatenformat. Da die Metadaten nicht komprimiert sind, ist es einfach genug, die gzip-Header zu entfernen und stattdessen ZIP-Datei-Header und einen zentralen Verzeichnisdatensatz anzuheften. Weitere Informationen finden Sie in der gzip-Formatspezifikation und der ZIP-Formatspezifikation .

bdonlan
quelle
40
Nee. Einfach cat file1.gz file2.gz file3.gz > allfiles.gz. Es ist wirklich so einfach :)
Bdonlan
1
technisch gesehen sind sie erhalten. Es ist nur so, dass vorhandene Tools im Allgemeinen nicht in der Lage sind, sie separat zu extrahieren. Vielleicht möchten Sie einen ZIP-Header und ein ZIP-Verzeichnis erstellen. Das ZIP-Format verwendet denselben zugrunde liegenden Komprimierungsalgorithmus. Es geht also nur darum, die (unkomprimierten) Metadaten zu ändern. Schauen Sie sich gzip.org/zlib/rfc-gzip.html (das Quellformat) und pkware.com/documents/casestudies/APPNOTE.TXT an .
Bdonlan
20
Besser als eine Zip-Datei mit GZ-Dateien zu erstellen, tarieren Sie sie einfach. Es ist das gleiche wie die catAntwort, aber mit einigen zusätzlichen Metadaten. Sie können sie später entpacken, um die ursprünglichen Dateinamen zu erhalten, und dann alle oder nur einige nach Bedarf entpacken.
Sorpigal
1
Viele Kommentare hier beziehen sich auf .zipDateien. Die Standardmethode zum Zusammenfügen mehrerer Dateien in einem komprimierten Archiv mithilfe des Algorithmus gzip (oder bzip2) ist die Verwendung von tar: tarFügt Dateien zusammen (unkomprimiert) und behält Dateinamen und -attribute bei. Die Aufgabe von gzip besteht darin, das Ergebnis zu komprimieren. Dies kann sogar in einem Schritt mit der -zOption von erfolgen tar. Die resultierenden Dateierweiterungen sind .tar.gzoder .tgz. Wenn Sie bereits komprimierte .gz-Dateien zusammenstellen möchten, verwenden Sie einfach tar. Es wird keine weitere Komprimierung durchgeführt, was für bereits komprimierte Dateien sinnvoll ist.
Daniel Alder
2
@alvas zcatdekomprimiert seine Eingabe, sodass Sie eine dekomprimierte Ausgabe mit einer .gzErweiterung erhalten.
Bdonlan
50

Hier ist, was man 1 gzipüber Ihre Anforderung sagt.

Mehrere komprimierte Dateien können verkettet werden. In diesem Fall extrahiert gunzip alle Mitglieder gleichzeitig. Beispielsweise:

gzip -c file1  > foo.gz
gzip -c file2 >> foo.gz

Dann

gunzip -c foo

ist äquivalent zu

cat file1 file2

Unnötig zu sagen, file1kann durch ersetzt werden file1.gz.

Sie müssen dies beachten:

gunzip extrahiert alle Mitglieder auf einmal

Um alle Mitglieder einzeln zu erhalten, müssen Sie etwas Zusätzliches verwenden oder schreiben, wenn Sie dies möchten.

Dies wird jedoch auch in der Manpage behandelt.

Wenn Sie eine einzelne Archivdatei mit mehreren Mitgliedern erstellen möchten, damit Mitglieder später unabhängig voneinander extrahiert werden können, verwenden Sie einen Archivierer wie tar oder zip. GNU tar unterstützt die -zOption, gzip transparent aufzurufen. gzip ist als Ergänzung zu Teer konzipiert, nicht als Ersatz.

Nehal Dattani
quelle
13

Verwenden Sie einfach Katze. Es ist sehr schnell (0,2 Sekunden für 500 MB für mich)

cat *gz > final
mv final final.gz

Sie können die Ausgabe dann mit zcat lesen, um sicherzustellen, dass sie hübsch ist:

zcat final.gz

Ich habe die andere Antwort von 'gz -c' ausprobiert, aber ich habe Müll gefunden, als ich bereits komprimierte Dateien als Eingabe verwendet habe (ich denke, es hat sie doppelt komprimiert).

PV:

Besser noch, wenn Sie es haben, "pv" anstelle von Katze:

pv *gz > final
mv final final.gz

Dies gibt Ihnen einen Fortschrittsbalken, wie es funktioniert, macht aber das Gleiche wie Katze.

matiu
quelle
11

Sie können eine TAR-Datei dieser Dateien erstellen und dann die TAR-Datei gzipen, um die neue gzip-Datei zu erstellen

tar -cvf newcombined.tar file1.gz file2.gz file3.gz
gzip newcombined.tar
Drona
quelle
8
Warum genau sollten Sie die neue TAR-Datei gzipen? Es ist bereits komprimiert (abgesehen von den Metadaten von tar, die klein sein sollten).
Thiton
2
Du hast recht. Es würde keinen großen Unterschied in der Dateigröße geben, ob Sie es gzipen oder nicht, da die einzelnen Dateien bereits komprimiert sind. Es ist nur so, weil er eine gzip-Datei aus den drei einzelnen Dateien haben wollte.
Drona
1
Das zusätzliche gzip verlangsamt nur den Zugriff auf den Inhalt ohne Gewinn. Es scheint mir, dass die OPs-Anforderung wirklich ist, dass das resultierende Archiv eine einzelne Datei ist, und es gibt keinen Grund anzunehmen, dass die resultierende Datei eine gzip-Datei sein sollte.
mc0e