A maneira mais rápida de resolver o tamanho descompactado de um arquivo GZIPPED grande

24

Depois que um arquivo é compactado, é possível consultá-lo rapidamente para dizer qual é o tamanho do arquivo descompactado (sem descompactá-lo), especialmente nos casos em que o arquivo descompactado tem mais de 4 GB.

De acordo com a RFC https://tools.ietf.org/html/rfc1952#page-5, você pode consultar os últimos 4 bytes do arquivo, mas se o arquivo não compactado for> 4 GB, o valor representa apenas ouncompressed value modulo 2^32

Esse valor também pode ser recuperado executando gunzip -l foo.gz, no entanto, a coluna "descompactada" apenas contém uncompressed value modulo 2^32novamente, presumivelmente enquanto lê o rodapé, conforme descrito acima.

Eu estava me perguntando se existe uma maneira de obter o tamanho do arquivo descompactado sem precisar descompactá-lo primeiro, isso seria especialmente útil no caso em que os arquivos compactados com gzip contêm 50 GB + de dados e levaria um tempo para descomprimir usando métodos como gzcat foo.gz | wc -c


EDIT: A limitação de 4 GB é reconhecida abertamente na manpágina do gziputilitário incluído no 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
fonte
2
+1 boa pergunta! Suspeito que a resposta seja não, esse formato de cabeçalho foi criado antes de prever o tamanho desses arquivos. Pensando nisso, gzipdeve ser mais antigo que muitos usuários nesta comunidade!
Celada
2
gzipsaiu em 1992. Eu ficaria surpreso se houvesse muitos jovens de 23 anos vagando por aqui. Tenho certeza de que existem alguns, mas pelo que posso dizer, a idade média é de cerca de 30 a 35 anos.
Bratchley
2
Pode ser um bom momento para mudar para o xzqual não há essa limitação. O GNU está mudando para xz.
Stéphane Chazelas
@ StéphaneChazelas Interessante. Infelizmente, os arquivos nos quais estou interessado estão fora do meu controle (ou seja, nós os recebemos compactados), mas certamente parece xz que 'resolveria' esse problema.
21415 djhworld

Respostas:

11

Eu acredito que a maneira mais rápida é modificar gzippara que o teste no modo detalhado produza o número de bytes descompactados; no meu sistema, com um arquivo de 7761108684 bytes, recebo

% 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

Para modificar o gzip (1.6, conforme disponível no Debian), o patch é o seguinte:

--- 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 {
Stephen Kitt
fonte
Ainda constrói os dados reais internamente, ou -tjá está otimizado nesse sentido? A melhoria é pequena o suficiente para parecer que você economizou apenas o tempo de saída.
Frostschutz
Sim, ele precisa descomprimir tudo para descobrir o tamanho original ... Portanto, isso economiza apenas o tempo de saída, mas acho que é tudo o que pode ser salvo.
Stephen Kitt
Interessante, sim, eu estava pensando que você precisaria alterar o código para que isso funcionasse. Infelizmente, na minha instância, os arquivos que me interessam não estão realmente no meu controle, eu os recebo de uma parte externa, portanto, não seria possível compactá-los. Eu acho que a única maneira de dar suporte total a arquivos de> 4 GB seria corrigir o gzip para ter um rodapé de 12 bytes, 4 bytes para CRC e 8 bytes (64 bits) para o tamanho do arquivo. No entanto, isso quebraria a compatibilidade com os gzips existentes!
21415 djhworld
A solução fornecida acima não envolve a compactação dos arquivos inicialmente, mesmo que eu esteja executando gzip; Eu apenas corro gzipnos arquivos compactados, que não os compactam novamente, apenas os verifica. (O adesivo é um rápido e suja prova-de-conceito, é necessário mais algumas alterações de trabalho com gunzip.)
Stephen Kitt
@StephenKitt Ah interessante! Um hack ainda melhor / mais sujo seria incorporar esses dados no FCOMMENTcampo. Dessa forma, os usuários podem consultar um intervalo de bytes para recuperar esses dados. Isso seria útil no meu caso, especialmente para itens armazenados no Amazon S3
djhworld
0

Se você precisar do tamanho de um arquivo compactado ou de um conjunto de arquivos, sua melhor aposta é usar tar -zou, em tar -jvez de gzip, tarincluir o tamanho do arquivo não compactado. Use lesspipepara espiar a lista de arquivos:

aptitude install lesspipe
lesspipe <compressed file> | less

Se lessestiver configurado para usar lesspipe:

less <compressed file>

Basta ter em mente que pode demorar muito tempo. No entanto, seu sistema permanece responsivo, o que permite eliminar o processo de descompressão.

Outra abordagem seria registrar a taxa compactada e consultar o arquivo [text]:

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

Requer computação para encontrar o tamanho real do arquivo.

Você também pode fazer o mesmo com tar, que é de fato o que faço com backups de grande porte, pois impede a execução de todo o processo de descompactação para obter apenas um tamanho ou nome de arquivo, por exemplo.


fonte
2
O tar.gz não precisa ser descomprimido completamente para obter a lista de todos os arquivos?
Frostschutz 7/02
De fato tem que ser. Essa é a única maneira em que consigo obter o tamanho do arquivo descompactado. Com tarvocê, o tamanho do arquivo original é registrado no arquivo morto. Eu não tenho certeza zipse comporta de maneira diferente, por outro lado.
11
Nesse ponto, o OP também pode executar o wc -ccomando.
Bratchley
@Bratchley, é claro. Mas levaria uma quantidade considerável de tempo para obter todos os resultados. Daí minhas duas sugestões para registrar tamanhos de arquivo.
0

Sobre o quê

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

numfmt --to=iec $(gzip -l file.gz|tail -n1|awk '{print $2}')
Syco
fonte
11
Isso não funciona para arquivos grandes, conforme explicado pelo OP.
Stephen Kitt
-2
gunzip -c $file | wc -c

Isso levará muito tempo, mas fornecerá o tamanho final em bytes.

usuario
fonte
5
É exatamente isso que o OP está tentando evitar ter que fazer.
depquid