web-dev-qa-db-ja.com

パイプを介して飛んでいるファイルを解凍する

Unzipなどのプログラムを標準出力で機能させることはできますか?状況は、その場で解凍されることになっているZipファイルをダウンロードしているところです。

関連問題: ダウンロードしたファイルをbashの標準出力にパイプするにはどうすればよいですか?

43
Alex

Zipファイルは実際にはコンテナ形式ですが、ファイルがメモリに簡単に収まる場合にパイプ(stdin)から読み取れない理由はありません。 Pythonスクリプトは、Zipファイルを標準入力として受け取り、現在のディレクトリまたは指定されている場合は指定されたディレクトリに内容を抽出します。

import zipfile
import sys
import StringIO
data = StringIO.StringIO(sys.stdin.read())
z = zipfile.ZipFile(data)
dest = sys.argv[1] if len(sys.argv) == 2 else '.'
z.extractall(dest)

このスクリプトは、1行に縮小してエイリアスとして作成できます。

alias unzip-stdin="python -c \"import zipfile,sys,StringIO;zipfile.ZipFile(StringIO.StringIO(sys.stdin.read())).extractall(sys.argv[1] if len(sys.argv) == 2 else '.')\""

Wgetの出力を簡単に解凍します。

wget http://your.domain.com/your/file.Zip -O - | unzip-stdin target_dir
22
Jason R. Coombs

これが期待どおりに機能することはほとんどありません。 Zipは圧縮形式だけでなく、コンテナ形式でもあります。 tarとgzip.bzip2の両方のジョブを1つにまとめます。そうは言っても、Zipに単一のファイルがある場合は、unzip -pを使用してファイルをstdoutに抽出できます。複数のファイルがある場合、ファイルの開始位置と停止位置を判別する方法はありません。

Stdinからの読み取りに関しては、unzipのマニュアルページには次の文があります。

Funzipを除いて、標準入力から読み取ったアーカイブはまだサポートされていません(アーカイブの最初のメンバーのみを抽出できます)。

Funzipで運がいいかもしれません。

18
David Pashley

やりたいことは、unzipに、引数としてではなく、標準入力でZIPファイルを作成することです。これは通常、gzipおよびtarの種類のツールで簡単にサポートされ、-引数。しかし、標準のunzipはそれを行いません(ただし、パイプへの抽出はサポートしています)。しかし、すべてが失われるわけではありません...

funzip マニュアルページを見てください。

ファイル引数のないfunzipはフィルターとして機能します。つまり、Zipアーカイブ(またはgzipで圧縮されたファイル)が標準入力にパイプ処理されていると想定し、アーカイブからstdoutに最初のメンバーを抽出します。 stdinがttyデバイスからのものである場合、funzipはこれが(バイナリ)圧縮データのストリームではないと想定し、代わりに短いヘルプテキストを表示します。ファイル引数がある場合、入力はstdinからではなく、指定されたファイルから読み取られます。

単一メンバーの抽出に制限があるため、funzipはtar(1)などの2次アーカイバープログラムと組み合わせて使用​​すると最も便利です。次のセクションには、テープへのディスクバックアップの場合のこの使用法を示す例が含まれています。

これは、ほとんどのLinuxアーカイブが通常TARで圧縮され、その後何らかの方法(gzip、bzipなど)でZIP圧縮されるという考えによく合います。これは、tar.Zip


funzipは、Info-Zipの原作者であるMark Adlerによって作成されていることに注意してください。彼はfunzip manページに書いています、

this functionality should be incorporated into unzip itself (future release).

ただし、そのような更新は周りに見られません。他のアーカイブ方法はTARで簡単に機能したので、Markはそれが不必要だと思ったと思います。

7
nik

Curlはデフォルトでインストールされるため、使用するのが好きです(-Lは、頻繁に発生するリダイレクトに必要です):

curl -L http://example.com/file.Zip | bsdtar -xvf - -C /path/to/directory/

ただし、bsdtarはデフォルトではインストールされておらず、funzipを機能させることができませんでした。

7
Todd Partridge

これは、同様の質問に対する 私の答え の再投稿です。

Zipファイル形式には、アーカイブの最後にディレクトリ(インデックス)が含まれています。このディレクトリは、アーカイブ内の各ファイルの場所を示しているため、アーカイブ全体を読み取ることなく、すばやくランダムにアクセスできます。

これは、パイプを介してZipアーカイブを読み取ろうとすると問題が発生するように見えます。インデックスは最後までアクセスされないため、ファイルが完全に読み取られて使用できなくなるまで、個々のメンバーを正しく抽出できません。 。そのため、アーカイブがパイプを介して提供される場合、ほとんどのZipデコンプレッサが単に失敗するのは当然のことです。

アーカイブの最後のディレクトリは、ファイルメタ情報がアーカイブに格納されるonlyの場所ではありません。さらに、冗長性を確保するために、個々のエントリのローカルファイルヘッダーにもこの情報が含まれています。

インデックスが利用できない場合、すべてのZipデコンプレッサがローカルファイルヘッダーを使用するわけではありませんが、tarおよびcpioフロントエンドはlibarchive(別名bsdtarおよびbsdcpio)にcanおよびwillパイプを介して読み取る場合は、次のことが可能です。

wget -qO- http://example.org/file.Zip | bsdtar -xvf-
5
ruario

Zshでは、次のことができます。

unzip =( curl http://example.com/someZipFile.Zip )
4
Ian Robertson

これを実行する最も簡単な一般的なユーティリティはjarです。これは、ファイル引数を渡さない場合にSTDINが使用されていると想定します。また、操作のためにtarプログラムと同様の引数を取ります。

例えばアーカイブの内容を一覧表示する

curl https://my.example.com/file.Zip | jar t

Javaは常にインストールされるわけではありませんが、それがインストールされているマシンでは、jarが最も便利な方法です。

4
Adrian

最も一般的なOSS実装であるInfo-Zipでは不可能です。さらに重要なのは、Zipアーカイブの構成のため、これは推奨されないことです。

フォーマットの変更が実行可能な場合は、代わりにtar(1)の使用を検討してください。ストリーミングされた入力/出力に非常に満足しており、実際にはデフォルトでそれを期待しています。

さらに、ファイル名に「-」を指定することで、アプリケーションがストリーム入出力を予期しているかどうかを確認できます。 Info-Zipは、ご想像のとおり、これを有効な引数として扱いません。

4
Dan Carley

私の答え の再投稿:

BusyBoxのunzipは、標準入力を取り、すべてのファイルを抽出できます。

wget -qO- http://downloads.wordpress.org/plugin/akismet.2.5.3.Zip | busybox unzip -

unzipの後のダッシュは、stdinを入力として使用するためのものです。

あなたもできます

cat file.Zip | busybox unzip -

しかし、それはunzip file.Zipの冗長です。

ディストリビューションがデフォルトでBusyBoxを使用している場合(Alpineなど)、unzip -を実行します。

3
Saftever

実際にはもう少し複雑なものが必要でした-特定のファイルが存在する場合はそれを抽出します。問題は、入力ファイルストリームがZipファイルではない可能性があることです。その場合、パイプを継続するために必要でした。これが私の解決策です(主にJason R. Coombsの解決策に感謝します)

python -c "import zipfile,sys,StringIO
data=sys.stdin.read()
try:
    z=zipfile.ZipFile(StringIO.StringIO(data))
    z.open(\"$1\")
    sys.stdout.write(z.read(\"$1\"))
except (RuntimeError, zipfile.BadZipfile):
    sys.stdout.write(data)"

これをマシンの「/ bin」フォルダに「単純な名前ではなく」「effpoptp」という名前のファイルとして保存したので、テストは次のようになります。

cat defaultModel.mwb|effpoptp "document.mwb.xml"

目的は、MySQL Workbenchファイルをバージョン管理することです。ファイルは、ワークベンチファイルとして指定されたxmlファイル、または完全なワークベンチファイルです。

1
SEoF