Быстрая конкатенация нескольких файлов GZip

93

У меня есть список файлов gzip:

file1.gz
file2.gz
file3.gz

Есть ли способ объединить или сжать эти файлы в один файл gzip без необходимости их распаковывать ?

На практике мы будем использовать это в веб-базе данных (CGI). Где Интернет получит запрос от пользователя, перечислит все файлы на основе запроса и представит их в пакетном файле обратно пользователю.

Никогда
источник

Ответы:

107

С помощью файлов gzip вы можете просто объединить файлы вместе, например:

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

Согласно gzip RFC ,

Файл gzip состоит из ряда «членов» (сжатых наборов данных). [...] Члены просто появляются в файле один за другим без дополнительной информации до, между или после них.

Обратите внимание, что это не совсем то же самое, что создание одного gzip-файла со связанными данными; среди прочего, сохраняются все исходные имена файлов. Однако похоже, что gunzip обрабатывает это как эквивалент конкатенации.

Поскольку существующие инструменты обычно игнорируют заголовки файлов для дополнительных членов, извлечь отдельные файлы из результата нелегко. Если вы хотите, чтобы это было возможно, вместо этого создайте ZIP-файл. ZIP и GZIP оба используют алгоритм DEFLATE для фактического сжатия (ZIP поддерживает некоторые другие алгоритмы сжатия, а также опцию - метод 8 соответствует сжатию GZIP); разница в формате метаданных. Поскольку метаданные не сжаты, достаточно просто удалить заголовки gzip и вместо этого добавить заголовки файлов ZIP и запись центрального каталога. См. Спецификацию формата gzip и спецификацию формата ZIP .

бдонлан
источник
41
Неа. Просто cat file1.gz file2.gz file3.gz > allfiles.gz. Это действительно так просто :)
bdonlan
1
технически говоря, они сохранены. Просто существующие инструменты обычно не имеют возможности извлекать их отдельно. Возможно, вы захотите изучить создание заголовка и каталога ZIP - формат ZIP использует тот же базовый алгоритм сжатия, поэтому это просто вопрос изменения (несжатых) метаданных. Взгляните на gzip.org/zlib/rfc-gzip.html (исходный формат) и pkware.com/documents/casestudies/APPNOTE.TXT .
bdonlan
20
Лучше, чем создавать zip-архив из файлов gz, - просто использовать их tar. Это то же самое, что и catответ, но с некоторыми дополнительными метаданными. Позже вы можете распаковать их, чтобы получить исходные имена файлов, а затем распаковать все или только несколько файлов по мере необходимости.
sorpigal 04
2
@alvas zcatраспаковывает свой ввод, чтобы получить распакованный вывод с .gzрасширением.
bdonlan 06
2
Очевидно, есть некоторые инструменты, которые по ошибке останавливаются, когда достигают конца первого элемента, запакованного с помощью gzip. github.com/pysam-developers/pysam/issues/…
Джереми Лейпциг
51

Вот что man 1 gzipговорит о вашем требовании.

Можно объединить несколько сжатых файлов. В этом случае gunzip извлечет всех участников сразу. Например:

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

затем

gunzip -c foo

эквивалентно

cat file1 file2

Само собой разумеется, file1можно заменить на file1.gz.

Вы должны заметить это:

gunzip распакует сразу всех участников

Итак, чтобы получить всех участников индивидуально, вам нужно будет использовать что-то дополнительное или написать, если вы хотите это сделать.

Однако это также рассматривается на странице руководства.

Если вы хотите создать один архивный файл с несколькими участниками, чтобы впоследствии члены могли быть извлечены независимо, используйте архиватор, такой как tar или zip. GNU tar поддерживает -zвозможность прозрачного вызова gzip. gzip разработан как дополнение к tar, а не как замена.

Нехал Даттани
источник
13

Просто используйте cat. Очень шустрый (у меня 0,2 секунды на 500 МБ)

cat *gz > final
mv final final.gz

Затем вы можете прочитать вывод с помощью zcat, чтобы убедиться, что он красивый:

zcat final.gz

Я попробовал другой ответ «gz -c», но в итоге я получил мусор при использовании уже сжатых файлов в качестве входных данных (я думаю, он дважды сжал их).

PV:

А еще лучше, если он у вас есть, вместо cat:

pv *gz > final
mv final final.gz

Это дает вам индикатор выполнения, но делает то же самое, что и cat.

матиу
источник
11

Вы можете создать tar-файл из этих файлов, а затем сжать tar-файл, чтобы создать новый файл gzip.

tar -cvf newcombined.tar file1.gz file2.gz file3.gz
gzip newcombined.tar
Дрона
источник
8
Почему именно нужно архивировать новый tar-файл? Он уже заархивирован (кроме метаданных tar, которые должны быть небольшими).
thiton
2
Ты прав. Не будет большой разницы в размере файла, независимо от того, сжаты вы его или нет, потому что отдельные файлы уже сжаты. Это просто потому, что он хотел получить файл gzip из трех отдельных файлов.
Drona
1
Дополнительный gzip просто замедляет доступ к контенту без всякой выгоды. Мне кажется, что требование OP действительно состоит в том, чтобы результирующий архив был одним файлом, и нет никаких оснований предполагать, что результирующий файл должен быть файлом gzip.
mc0e