Самый быстрый способ определения несжатого размера большого файла GZIPPED

24

После того, как файл распакован, существует ли способ быстро запросить его, чтобы сказать, каков размер несжатого файла (без распаковки), особенно в случаях, когда размер несжатого файла составляет> 4 ГБ.

Согласно RFC https://tools.ietf.org/html/rfc1952#page-5 вы можете запросить последние 4 байта файла, но если несжатый файл был> 4 ГБ, то значение просто представляетuncompressed value modulo 2^32

Это значение также можно получить, запустив его gunzip -l foo.gz, однако «несжатый» столбец просто содержит uncompressed value modulo 2^32снова, предположительно, поскольку он читает нижний колонтитул, как описано выше.

Мне было просто интересно, есть ли способ получить размер несжатого файла без необходимости сначала распаковывать его, это было бы особенно полезно в случае, когда сжатые файлы содержат более 50 ГБ данных и потребуется некоторое время для распаковки с использованием таких методов, как gzcat foo.gz | wc -c


РЕДАКТИРОВАТЬ: ограничение 4 ГБ открыто подтверждается на manстранице gzipутилиты, включенной в 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.
djhworld
источник
2
+1 хороший вопрос! Я подозреваю, что ответ - нет, этот формат заголовка был разработан за время до того, как ожидались такие размеры файлов. Думая об этом, gzipдолжен быть старше, чем многие пользователи в этом сообществе!
Селада,
2
gzipвышел в 1992 году. Я был бы удивлен, если бы здесь было много 23-летних. Я уверен, что есть некоторые, но из того, что я могу сказать, средний возраст составляет приблизительно 30-35.
Братчли
2
Может быть, самое время перейти к тому, у xzкоторого нет этого ограничения. GNU переключается на xz.
Стефан Шазелас
@ StéphaneChazelas Интересно. К сожалению, файлы, которые меня интересуют, находятся вне моего контроля (т.е. мы получаем их сжатыми), но, похоже, xz это «решит» эту проблему.
djhworld

Ответы:

11

Я полагаю, что самый быстрый способ - это изменить, gzipчтобы тестирование в подробном режиме выводило количество распакованных байтов; в моей системе, с 7761108684-байтовым файлом, я получаю

% 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

Чтобы изменить gzip (1.6, как доступно в Debian), патч выглядит следующим образом:

--- 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 {
Стивен Китт
источник
Он все еще строит фактические данные внутри или -tуже оптимизирован в этом отношении? Улучшение достаточно маленькое, чтобы выглядело так, как будто вы только сэкономили время вывода.
frostschutz
Да, нужно распаковать все, чтобы выяснить исходный размер ... Так что это только экономит время вывода, но я думаю, что это все, что можно сохранить.
Стивен Китт
Интересно, да, я думал, что вам нужно изменить код, чтобы на самом деле заставить это работать. К сожалению, в моем случае файлы, которые меня интересуют, на самом деле не находятся под моим контролем, я получаю их от внешней стороны, поэтому я не смог бы сначала сжать их. Я думаю, что единственный способ полностью поддерживать файлы размером> 4 Гбайт - это пропатчить gzip, чтобы иметь 12-байтовый нижний колонтитул, 4 байта для CRC и 8 байтов (64-битный) для размера файла. Однако это нарушит обратную совместимость с существующими gzips!
djhworld
Решение, которое я привел выше, изначально не включает сжатие файлов, хотя я работаю gzip; Я просто запускаю gzipсжатые файлы, которые не сжимают их, а просто проверяют. (Патч - быстрое и грязное доказательство концепции, для работы с ним требуется еще несколько изменений gunzip.)
Стивен Китт,
@ StefhenKitt Ах интересно! Еще лучше / грязнее взломать было бы внедрить эти данные в FCOMMENTполе. Таким образом, пользователи могут запросить диапазон байтов, чтобы получить эти данные. Это было бы полезно в моем случае, особенно для предметов, хранящихся в Amazon S3
djhworld
0

Если вам нужен размер сжатого файла или набора файлов, лучше всего использовать tar -zили tar -jвместо того , чтобы, gzipкак tarвключает несжатый размер файлов. Используйте, lesspipeчтобы просмотреть список файлов:

aptitude install lesspipe
lesspipe <compressed file> | less

Если lessнастроен для использования lesspipe:

less <compressed file>

Просто имейте в виду, что это может занять очень много времени. Однако ваша система остается отзывчивой, что позволяет убить процесс распаковки.

Другой подход - записать сжатый коэффициент и запросить этот [текстовый файл]:

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

Это требует вычисления, чтобы найти реальный размер файла.

Вы также можете сделать то же самое с tar, что на самом деле то же самое , что я делаю с резервными копиями большого размера, так как это препятствует выполнению всего процесса распаковки, например, для получения только размера или имени файла.


источник
2
Не нужно ли полностью распаковывать tar.gz, чтобы получить список всех файлов?
frostschutz
Так и должно быть. Это единственный способ получить несжатый размер файла. С tarвами в архиве записан исходный размер файла. Я не уверен, zipведет себя по-другому, с другой стороны.
1
В этот момент OP может также выполнить wc -cкоманду.
Братчли
@ Брэтчли, конечно. Но чтобы получить все результаты, понадобится немало времени. Отсюда два моих предложения регистрировать размеры файлов.
0

Как насчет

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

numfmt --to=iec $(gzip -l file.gz|tail -n1|awk '{print $2}')
Сико
источник
1
Это не работает для больших файлов, как объясняется в OP.
Стивен Китт
-2
gunzip -c $file | wc -c

Это займет много времени, но даст вам окончательный размер в байтах.

Ник
источник
5
Это именно то, что ОП пытается избежать необходимости делать.
Депвид