web-dev-qa-db-ja.com

UNIXでzlibデータを解凍する方法は?

次のようにして、Pythonでzlib圧縮データを作成しました。

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

(またはシェルのワンライナー:echo -n '...' | python2 -c 'import sys,zlib; sys.stdout.write(zlib.compress(sys.stdin.read()))' > /tmp/data

次に、シェルでデータを解凍します。 zcatuncompressも機能しません:

_$ 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
_

私はgzipのようなファイルを作成したようですが、ヘッダーはありません。残念ながら、そのような生データをgzipのマニュアルページに解凍するオプションはありません。また、zlibパッケージには実行可能なユーティリティが含まれていません。

生のzlibデータを解凍するユーティリティはありますか?

121
mykhal

標準 Shell-script + gzip を使用して解凍することもできます、または openssl を使用していない、または使用したい場合。
コツは、 gzipマジックナンバーを付加し、_zlib.compress_からの実際のデータにmethod を圧縮することです。

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

編集:
@ d0sbootsがコメントしました:RAW Deflateデータの場合、さらに2つのnullバイトを追加する必要があります:
→__"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00"_

SOに関するこのQ は、このアプローチに関する詳細情報を提供します。そこでの答えは、8バイトのフッターもあることを示唆しています。

ユーザーの@ Vitali-Kushnerと@ mark-besseyは、ファイルが切り捨てられた場合でも成功したと報告しているため、gzipフッターは厳密には必要ないようです。

@ tobias-kienzlerは bashrc に対してこの関数を提案しました:
zlipd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - [email protected] |gzip -dc)

146
wkpark
zlib-flate -uncompress < FILE

私はこれを試してみましたが、うまくいきました。

zlib-flateはパッケージqpdfにあります(他の回答のコメントによると、Debian SqueezeおよびFedora 23の場合)

(OpenSSL回答の下にコメントとしてこれを提供したユーザー@tinoに感謝します。簡単にアクセスできるように適切な回答にされました。)

81
Catskul

私は解決策を見つけました(可能な解決策の1つ)、それはopensslを使用しています:

$ openssl zlib -d < /tmp/data

または

$ openssl zlib -d -in /tmp/data

*注:最近のopensslバージョン> = 1.0.0でzlib機能が使用できるようです(OpenSSLはzlibまたはzlib-dynamicオプションで構成/構築する必要があります。後者はデフォルトです)

63
mykhal

Zlib圧縮ライブラリの共著者である Mark Adler から pigz をお勧めします。 pigzを実行して、使用可能なフラグを確認します。

君は気づくよ:

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

-dフラグを使用して解凍できます。

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

「test」という名前のファイルを想定します。

  • pigz -z test-test.zzという名前のzlib圧縮ファイルを作成します
  • pigz -d -z test.zz-test.zzを解凍されたテストファイルに変換します

OSXではbrew install pigzを実行できます

30
snodnipper

zlib gzipで使用される圧縮を実装しますが、ファイル形式は実装しません。代わりに、それ自体がgzipを使用する zlib module を使用する必要があります。

import gzip
s = '...'
with gzip.open('/tmp/data', 'w') as f:
    f.write(s)
11
Jeremy Banks

これはそれを行うかもしれません:

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)

次に、次のように実行します。

$ python expander.py data/*
3
Jeremy Banks

完全なPOSIX準拠のUNIX(正式に認定された!)であるmacOSでは、OpenSSLzlibをサポートせず、zlib-flateもありません。すべてのPythonソリューションでは、最初のソリューションではZipデータがファイルに含まれている必要があり、他のすべてのソリューションではPythonスクリプトを作成する必要があります。

コマンドラインのワンライナーとして使用でき、STDINパイプを介して入力を取得し、新しくインストールされたmacOSでそのまま使用できるPerlベースのソリューションを次に示します。

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

より適切にフォーマットされたPerlスクリプトは次のようになります。

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

サンプルプログラムzpipe.cここにあります Mark Adler自身(zlibライブラリのソース配布に付属)は、生のzlibデータを使用するこれらのシナリオに非常に役立ちます。 cc -o zpipe zpipe.c -lzでコンパイルして解凍します:zpipe -d < raw.zlib > decompressed-dフラグなしで圧縮を行うこともできます。

3
Henno Brandsma

これを使用してzlibで圧縮できます。

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

そしてこれは空気を抜くために:

openssl enc -z -none -d < /file/to/deflate
1
Danny R

EIDAS関連コードの開発中に、SSO(SingleSignOn)SAMLRequest paramをデコードするbashスクリプトを思いつきました。これは通常、base64とraw-deflate(php gzdeflate)によってエンコードされます

#!/bin/bash
# file decode_saml_request.sh

urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }

if [[ $contents == *"SAMLRequest" ]]; then
  # extract param SAMLRequest from URL, strip all following params
  contents=$(cat ${1} | awk -F 'SAMLRequest=' '{print $2}' | awk -F '&' '{print $1}')
else
  # work with raw base64 encoded string
  contents=$(cat ${1})
fi

# add gzip raw-deflate header bytes and gunzip (`gzip -dc` can be replaced by `gunzip`)
printf "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00" | cat - <(echo `urldecode $contents` | base64 -d) | gzip -dc

こんな風に使えます

> decode_saml_request.sh /path/to/file_with_sso_url
# or
> echo "y00tLk5MT1VISSxJBAA%3D" | decode_saml_request.sh

スクリプトはGistとしてもここに公開されています: https://Gist.github.com/smarek/77dacb9703ac8b715b5eced5314d5085 この答えは維持しないかもしれませんが、ソースGistは維持します

0
Marek Sebera