Szybka konkatenacja wielu plików GZip

93

Mam listę plików gzip:

file1.gz
file2.gz
file3.gz

Czy istnieje sposób na połączenie tych plików lub spakowanie ich do jednego pliku gzip bez konieczności ich dekompresowania ?

W praktyce użyjemy tego w internetowej bazie danych (CGI). Gdzie sieć otrzyma zapytanie od użytkownika i wyświetli listę wszystkich plików na podstawie zapytania i przedstawi je w pliku wsadowym z powrotem do użytkownika.

neversaint
źródło

Odpowiedzi:

107

Dzięki plikom gzip możesz po prostu połączyć pliki ze sobą, na przykład:

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

Zgodnie z RFC gzip ,

Plik gzip składa się z szeregu elementów członkowskich (skompresowanych zestawów danych). […] Członkowie po prostu pojawiają się jeden po drugim w aktach, bez żadnych dodatkowych informacji przed nimi, między nimi ani po nich.

Zauważ, że nie jest to dokładnie to samo, co budowanie pojedynczego pliku gzip z połączonych danych; między innymi zachowywane są wszystkie oryginalne nazwy plików. Jednak gunzip wydaje się traktować to jako odpowiednik konkatenacji.

Ponieważ istniejące narzędzia generalnie ignorują nagłówki nazw plików dla dodatkowych elementów, nie jest łatwo wyodrębnić pojedyncze pliki z wyniku. Jeśli chcesz, aby było to możliwe, zamiast tego utwórz plik ZIP. ZIP i GZIP używają algorytmu DEFLATE do rzeczywistej kompresji (ZIP obsługuje niektóre inne algorytmy kompresji, a także opcję - metoda 8 to ta, która odpowiada kompresji GZIP); różnica tkwi w formacie metadanych. Ponieważ metadane są nieskompresowane, wystarczy usunąć nagłówki gzip i zamiast tego dołączyć nagłówki plików ZIP i rekord katalogu centralnego. Zapoznaj się ze specyfikacją formatu gzip i specyfikacją formatu ZIP .

bdonlan
źródło
41
Nie. Po prostu cat file1.gz file2.gz file3.gz > allfiles.gz. To naprawdę takie proste :)
bdonlan
1
technicznie rzecz biorąc, są zachowane. Tyle, że istniejące narzędzia na ogół nie mają możliwości wyodrębnienia ich osobno. Możesz przyjrzeć się tworzeniu nagłówka i katalogu ZIP - format ZIP wykorzystuje ten sam podstawowy algorytm kompresji, więc wystarczy zmienić (nieskompresowane) metadane. Spójrz na gzip.org/zlib/rfc-gzip.html (format źródłowy) i pkware.com/documents/casestudies/APPNOTE.TXT .
bdonlan
20
Lepsze niż budowanie zip z plików gz, po prostu taruj je. To jest to samo, co catodpowiedź, ale z dodatkowymi metadanymi. Możesz później rozpakować je, aby uzyskać oryginalne nazwy plików, a następnie rozpakować wszystkie lub tylko kilka w razie potrzeby.
sorpigal
2
@alvas zcatdekompresuje swoje dane wejściowe, dzięki czemu otrzymasz zdekompresowane wyjście z .gzrozszerzeniem.
bdonlan
2
Najwyraźniej istnieją narzędzia, które omyłkowo zatrzymają się, gdy dotrą do końca pierwszego członka skompresowanego gzipem. github.com/pysam-developers/pysam/issues/…
Jeremy Leipzig
51

Oto, co man 1 gzipmówi o twoich wymaganiach.

Można łączyć wiele skompresowanych plików. W takim przypadku narzędzie gunzip wyodrębni jednocześnie wszystkich członków. Na przykład:

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

Następnie

gunzip -c foo

jest równa

cat file1 file2

Nie trzeba dodawać, że file1można go zastąpić file1.gz.

Musisz to zauważyć:

gunzip usunie wszystkich członków jednocześnie

Tak więc, aby zebrać wszystkich członków indywidualnie, będziesz musiał użyć czegoś dodatkowego lub napisać, jeśli chcesz to zrobić.

Jednak jest to również omówione na stronie podręcznika.

Jeśli chcesz utworzyć pojedynczy plik archiwum z wieloma członkami, aby członkowie mogli później być rozpakowywani niezależnie, użyj archiwizatora, takiego jak tar lub zip. GNU tar obsługuje -zopcję przezroczystego wywoływania programu gzip. gzip został zaprojektowany jako uzupełnienie tar, a nie jako zamiennik.

Nehal Dattani
źródło
13

Po prostu użyj kota. Jest bardzo szybki (dla mnie 0,2 sekundy za 500 MB)

cat *gz > final
mv final final.gz

Następnie możesz przeczytać dane wyjściowe za pomocą zcat, aby upewnić się, że są ładne:

zcat final.gz

Wypróbowałem drugą odpowiedź, „gz -c”, ale skończyło się na śmieciach podczas używania plików spakowanych już gzipem jako danych wejściowych (wydaje mi się, że to dwukrotnie je skompresowało).

PV:

Jeszcze lepiej, jeśli go masz, `` pv '' zamiast kota:

pv *gz > final
mv final final.gz

Daje ci to pasek postępu, ponieważ działa, ale robi to samo, co cat.

matiu
źródło
11

Możesz utworzyć plik tar z tych plików, a następnie spakować go gzipem, aby utworzyć nowy plik gzip

tar -cvf newcombined.tar file1.gz file2.gz file3.gz
gzip newcombined.tar
Drona
źródło
8
Dlaczego dokładnie należy zgzipować nowy plik tar? Jest już spakowany (poza metadanymi tar, które powinny być małe).
thiton
2
Masz rację. Nie byłoby dużej różnicy w rozmiarze pliku, niezależnie od tego, czy chcesz go spakować, czy nie, ponieważ poszczególne pliki są już spakowane. To tylko dlatego, że chciał mieć plik gzip z trzech pojedynczych plików.
Drona
1
Dodatkowy plik gzip po prostu spowalnia dostęp do zawartości bez żadnych korzyści. Wydaje mi się, że wymaganiem OPs jest tak naprawdę, aby wynikowe archiwum było pojedynczym plikiem i nie ma powodu, aby przypuszczać, że wynikowy plik powinien być plikiem gzip.
mc0e