Найшвидший спосіб опрацювати нестиснений розмір великого файлу 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.