Самый быстрый способ определения несжатого размера большого файла 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.

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
Это именно то, что ОП пытается избежать необходимости делать.
— Депвид
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.