Найшвидший спосіб опрацювати нестиснений розмір великого файлу GZIPPED


24

Як тільки файл gzipped, чи є спосіб швидкого запиту, щоб він сказав, який розмір нестисненого файлу (не розпаковуючи його), особливо у випадках, коли нестиснений файл має розмір> 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знову, імовірно, він читає колонтитул, як описано вище.

Мені було просто цікаво, чи є спосіб отримати розмір нестисненого файлу, не спершу розпаковувати його, це було б особливо корисно в тому випадку, коли gzipped файли містять 50 ГБ + даних і знадобиться деякий час, щоб розпакувати за допомогою таких методів, як gzcat foo.gz | wc -c


EDIT: Обмеження 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Я був би здивований, якби тут багато блукали 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.)
— Стівен Кітт

@StephenKitt Ах цікаво! Ще кращим / бруднішим хаком було б вбудовувати ці дані в FCOMMENTполе. Таким чином користувачі можуть запитувати діапазон байтів, щоб отримати ці дані. Це було б корисно в моєму випадку, особливо для предметів, що зберігаються в Amazon S3
— djhworld

0

Якщо вам потрібен розмір стисненого файлу або набору файлів, найкраще скористатися tar -zабо tar -jзамість того gzip, щоб він tarвключав розмір нестиснених файлів. Використовуйте, lesspipeщоб зазирнути до списку файлів:

aptitude install lesspipe
lesspipe <compressed file> | less

Якщо lessналаштовано для використання lesspipe:

less <compressed file>

Пам'ятайте, що це може зайняти дуже багато часу. Однак ваша система залишається чуйною, що дозволяє вбити процес декомпресії.

Іншим підходом було б записати стиснене співвідношення та запит, що замість нього [text] файл:

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

Це вимагає обчислень, щоб знайти реальний розмір файлу.

Ви також можете зробити те ж саме tar, що, власне, я роблю з резервними копіями великих розмірів, оскільки це заважає виконувати весь процес декомпресії, щоб отримати лише розмір або ім’я файлу, наприклад.


2
Чи не потрібно tar.gz повністю декомпресувати, щоб отримати список усіх файлів?
— frostschutz

Справді це має бути. Це єдиний спосіб, який я можу придумати, щоб отримати розмір нестисненого файлу. З tarвами вихідний розмір файлу увійшов до архіву. Я не впевнений, що zipповодиться інакше, з іншого боку.

1
У цей момент ОП також може виконати wc -cкоманду.
— Братчлі

@Bratchley звичайно. Але для отримання всіх результатів знадобиться чимала кількість часу. Звідси мої дві пропозиції щодо журналу розмірів файлів.

0

Як щодо

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

numfmt --to=iec $(gzip -l file.gz|tail -n1|awk '{print $2}')

1
Це не працює для великих файлів, як пояснено в ОП.
— Стівен Кітт

-2
gunzip -c $file | wc -c

Це займе багато часу, але надасть остаточний розмір у байтах.


5
Це саме те, що ОП намагається уникати.
— деквід
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.