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


39

標準出力で解凍または同様のプログラムを動作させることはできますか?状況は、その場で解凍されるはずのzipファイルをダウンロードしていることです。

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


これは実行可能であるように見えましたが、zipが単一のファイルのみを含む場合、zipを抽出し、ファイルを別のコマンドにパイプすることしかできないようです。マルチファイルzipから特定のファイルを抽出したかった。パイピングの代わりに、複数のコマンドをチェーン化するように切り替えました 'unzip file.zip / path / file && dostuff / path / file && rm -rf / path'元の質問に答えずに、一時ファイルが作成される結果、必要。
スタンクルドジール

pigzをチェックしてください。パイプで使用します。 andrew.tumblr.com/post/2316602611
dmourati

回答:


22

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

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

1
あなたとpython rock !!!
ファリッドノウリネシャット

3
素敵なワンライナー、およびファイルがメモリに収まらなければならないことを示すための+1。(残念ながら、ファイル形式の構造により、pkzipファイルを解凍する方法はありません)。
lxgr

2
これは、抽出する前にメモリ内のすべてをバッファ
リング

1
ファイルがメモリに簡単に収まることが十分に正確でない場合、ストリームとして読み取れない理由はありません。内容を抽出する前にzipアーカイブ全体をメモリにバッファリングすることを強制される理由は、特にストリームとして読み取ることができないためです。もちろん、zipアーカイブをファイルに書き込まないようにすることは依然として有用です。
ホーカンLindqvist

これはストリームではなく、次の.read()メソッドを使用してメモリ内のファイル全体を読み取っています
Romuald Brunet

17

これは期待どおりに機能する可能性は低いです。Zipは単なる圧縮形式ではなく、コンテナ形式でもあります。tarとgzip.bzip2の両方のジョブを1つにロールアップします。ただし、zipに単一のファイルがある場合は、unzip -pを使用してファイルを標準出力に抽出できます。複数のファイルがある場合、ファイルの開始場所と停止場所を伝える方法はありません。

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

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

funzipを使用すると幸運になるかもしれません。


zipに複数のファイルがある場合、-pはファイル名をパラメーターとして使用して単一のファイルを印刷できます。unzip -p temp.zip file-inside-zip
Taavi Ilves

7

あなたがしたいのは、unzip引数としてではなく標準入力でZIP形式のファイルを取ることです。これは通常、容易でサポートされているgziptarの種類とツールの-引数。しかし、標準unzipはそれを行いません(ただし、パイプへの抽出はサポートしています)。しかし、すべてが失われるわけではありません...

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

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

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

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


funzipInfo-ZIPの原作者であるMark Adlerによって書かれていることは注目に値します。彼はfunzipのmanページに書いています、

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

ただし、そのような更新は見られません。他のアーカイブ方法はTARで簡単に機能したため、Markはそれを不要であると判断したと思われます。


ただのコメント。解凍するオプションとしてpythonまたは任意の言語が必要な人もいます。主な例は、システムにtarまたはunzipを含まないHerokuです。回避策は、許可されているJavaをインストールしてjarを使用することです。
ニック14

この回答には、funzipおよび同様のツールの制限(特に、アーカイブの最初のメンバーのみを表示できる機能)の制限に関する詳細があります。unix.stackexchange.com
Joshua Goldberg

6

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

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

ただし、bsdtarはデフォルトでインストールされていないためfunzip、作業を開始できませんでした。


複数のファイルでも
正常に動作し

5

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

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

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

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

インデックスが利用できない場合ではない、すべてのZIP解凍器は、ローカル・ファイル・ヘッダーを使用しますが、(bsdtarとbsdcpio別名)作者libarchiveにtarとcpioのフロントエンドは、となりますことができ、パイプを通して読んで次のことが可能であることを意味するときに行います。

wget -qO- http://example.org/file.zip | bsdtar -xvf-

4

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

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

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



3

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

たとえば、アーカイブのコンテンツをリストする

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

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


3

私の答えの再投稿:

BusyBox unzipはstdinを使用してすべてのファイルを抽出できます。

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 -ます。


1

実際には、もう少し複雑なものが必要でした。特定のファイルが存在する場合はそれを抽出します。難点は、入力ファイルストリームが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ファイルです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.