Como descompactar dados zlib no UNIX?

106

Eu criei dados compactados com zlib no Python, assim:

import zlib
s = '...'
z = zlib.compress(s)
with open('/tmp/data', 'w') as f:
    f.write(z)

(ou de uma linha com casca: echo -n '...' | python2 -c 'import sys,zlib; sys.stdout.write(zlib.compress(sys.stdin.read()))' > /tmp/data)

Agora, quero descompactar os dados no shell. Nem zcatnem uncompresstrabalho:

$ cat /tmp/data | gzip -d -
gzip: stdin: not in gzip format

$ zcat /tmp/data 
gzip: /tmp/data.gz: not in gzip format

$ cat /tmp/data | uncompress -
gzip: stdin: not in gzip format

Parece que eu criei um arquivo semelhante ao gzip, mas sem nenhum cabeçalho. Infelizmente, não vejo nenhuma opção para descompactar esses dados brutos na página do manual gzip, e o pacote zlib não contém nenhum utilitário executável.

Existe um utilitário para descompactar dados brutos do zlib?

mykhal
fonte
Há muitas respostas adicionais aqui: stackoverflow.com/questions/3178566/deflate-command-line-tool
Jack O'Connor

Respostas:

140

Também é possível descompactá-lo usando o + padrão , se você não tiver, ou quiser usar o ou outras ferramentas.
O truque é anexar o número mágico gzip e compactar o método aos dados reais de zlib.compress:

printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - /tmp/data |gzip -dc >/tmp/out

Edições:
@ d0sboots comentadas: Para dados RAW Deflate, você precisa adicionar mais 2 bytes nulos:
"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00"

Este Q on SO fornece mais informações sobre essa abordagem. Uma resposta lá sugere que também há um rodapé de 8 bytes.

Os usuários @ Vitali-Kushner e @ mark-bessey relataram sucesso, mesmo com arquivos truncados, portanto, um rodapé gzip não parece estritamente necessário.

@ tobias-kienzler sugeriu esta função para o :
zlipd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - $@ |gzip -dc)

wkpark
fonte
O gzip não funciona, mas o zlib-flate funciona (fluxo de conteúdo da página em pdf).
Daneel S. Yaitskov
69

O usuário @tino comentou abaixo a resposta do OpenSSL, mas acho que isso deve ser separado:

zlib-flate -uncompress < FILE

Eu tentei isso e funcionou para mim.

zlib-flatepode ser encontrado no pacote qpdf(no Debian Squeeze e no Fedora 23, de acordo com os comentários em outras respostas)

Catskul
fonte
3
Em contraste com as outras respostas, esta funciona no OS X.
polym
2
@polym, como você foi zlib-flate instalado no macOS? Eu não vejo em lugar algum.
Curinga
4
@Wildcard desculpe pela resposta tardia. Eu acho que ele veio com o qpdfpacote que eu instalei brewcomo mencionado no comentário acima - ou veja a última frase desta resposta :). Além disso, qpdfé muito legal, então dê uma olhada também se tiver tempo!
Polym16
brew install qpdf, então o comando listado acima :-) obrigado!
Fernando Gabrieli
60

Eu encontrei uma solução (uma das possíveis), está usando o openssl :

$ openssl zlib -d < /tmp/data

ou

$ openssl zlib -d -in /tmp/data

* OBSERVAÇÃO: a funcionalidade zlib está aparentemente disponível nas versões recentes do openssl> = 1.0.0 (o OpenSSL deve ser configurado / construído com a opção zlib ou zlib-dynamic, a última é o padrão)

mykhal
fonte
25
No Debian Squeeze (que possui o OpenSSL 0.9.8), existe zlib-flateo qpdfpacote. Pode ser usado como zlib-flate -uncompress < FILE.
Tino
7
zlib foi removido das últimas versões do OpenSSL então esta dica é é @Tino muito útil
Alexandr Kurilin
1
Obrigado. Esta solução fornece uma experiência melhor na descompactação de arquivos de entrada curtos do que a resposta usando "gzip" ("openssl" descompactou o máximo que pôde enquanto "gzip" interrompeu a impressão "final de arquivo inesperado").
Daniel K.
2
@Tino esta deve ser uma resposta em separado
Catskul
1
@Tino, também está disponível no pacote qpdf no Fedora 23. Alexandr Kurilin, zlib ainda está disponível no 1.0.2d-fips.
maxschlepzig
28

Eu recomendo o pigz de Mark Adler , co-autor da biblioteca de compactação zlib. Execute pigzpara ver os sinalizadores disponíveis.

Vais aperceber-te:

-z --zlib Compress to zlib (.zz) instead of gzip format.

Você pode descompactar usando a -dbandeira:

-d --decompress --uncompress Decompress the compressed input.

Supondo que um arquivo chamado 'teste':

  • pigz -z test - cria um arquivo compactado zlib chamado test.zz
  • pigz -d -z test.zz - converte test.zz no arquivo de teste descompactado

No OSX você pode executar brew install pigz

snodnipper
fonte
7
Boa descoberta! Parece que ele pode detectar arquivos zlib por si só, então unpigz test.zztambém funcionará.
Stéphane Chazelas 26/09/16
não descompactou meus dados.
cybernard 26/01
1
@cybernard talvez você não tenha um arquivo zlib. verifique com:$>file hello.txt.zz hello.txt.zz: zlib compressed data
snodnipper 01/02
11

zlibimplementa a compactação usada pelo gzip, mas não o formato do arquivo. Em vez disso, você deve usar o gzipmódulo , que ele próprio usa zlib.

import gzip
s = '...'
with gzip.open('/tmp/data', 'w') as f:
    f.write(s)
Jeremy Banks
fonte
ok, mas minha situação é que eu tenho dezenas / centenas de milhares desses arquivos criados, então .. :)
1
então ... seus arquivos estão incompletos. Talvez você precise descompactá-los zlibe recomprimi-los gzip, se ainda não tiver os dados originais.
Greg Hewgill
6
@mykhal, por que você criou dezenas de milhares de arquivos antes de verificar se era possível descompactá-los?
3
harpyon, eu posso descompactar-los, eu só me pergunto o que mais ou menos comum urility ou configurações zgip pode ser usado para que, se eu não quiser fazê-lo em python novamente
3

Isso pode fazer isso:

import glob
import zlib
import sys

for filename in sys.argv:
    with open(filename, 'rb') as compressed:
        with open(filename + '-decompressed', 'wb') as expanded:
            data = zlib.decompress(compressed.read())
            expanded.write(data)

Em seguida, execute-o assim:

$ python expander.py data/*
Jeremy Banks
fonte
obrigado, eu sei sobre zlib.decompress. provavelmente eu usaria alguma função de caminhada. Eu não tenho certeza se shell iria lidar com o meu enorme quantidade de arquivos com wildcard glob :)
O arquivo criado pelo expandido ainda faz check-out como "dados compactados zlib" para mim, usando o filecomando shell ? Como é isso?
K.-Michael Aye
Nope não funciona para mim, mesmo com o cabeçalho falso.
cybernard 26/01
3

O programa de exemplo zpipe.c encontrado aqui pelo próprio Mark Adler (fornecido com a distribuição de origem da biblioteca zlib) é muito útil para esses cenários com dados brutos do zlib. Compilar com cc -o zpipe zpipe.c -lze para descomprimir: zpipe -d < raw.zlib > decompressed. Também pode fazer a compactação sem a -dbandeira.

Henno Brandsma
fonte
2

No macOS, que é um UNIX completo compatível com POSIX (certificado formalmente!), OpenSSLNão há zlibsuporte, não házlib-flate e, embora a primeira solução funcione tão bem quanto todas as soluções Python, a primeira solução exige que os dados ZIP estejam em um arquivo e todas as outras soluções forçam você a criar um script Python.

Aqui está uma solução baseada em Perl que pode ser usada como uma linha de comando, obtém sua entrada via STDIN pipe e que funciona imediatamente com um macOS instalado recentemente:

cat file.compressed | perl -e 'use Compress::Raw::Zlib;my $d=new Compress::Raw::Zlib::Inflate();my $o;undef $/;$d->inflate(<>,$o);print $o;'

Melhor formatado, o script Perl fica assim:

use Compress::Raw::Zlib;
my $decompressor = new Compress::Raw::Zlib::Inflate();
my $output;
undef $/;
$decompressor->inflate(<>, $output);
print $output;
Mecki
fonte
1

Você pode usar isso para compactar com o zlib:

openssl enc -z -none -e < /file/to/deflate

E isso para desinflar:

openssl enc -z -none -d < /file/to/deflate
Danny R
fonte
4
unknown option '-z'no Ubuntu 16.04 eOpenSSL 1.0.2g 1 Mar 2016
Tino
2
mesmo erro no Mac
K.-Michael Aye
-3
zcat -f infile > outfile 

funciona para mim no fedora25

sigxcpu
fonte
1
zcatsó funciona com arquivos no formato gzip.
Anthony Geoghegan