入力としてwgetの出力をunzipにリダイレクトする方法は?


131

このリンクからファイルをダウンロードする必要があります。ダウンロードしたファイルはzipファイルで、現在のフォルダーで解凍する必要があります。

通常は、まずダウンロードしてから、unzipコマンドを実行します。

$ wget http://www.vim.org/scripts/download_script.php?src_id=11834 -O temp.zip
$ unzip temp.zip

ただし、この方法では、2つのコマンドを実行し、最初のコマンドが完了するのを待って次のコマンドを実行する必要があります。また、ファイルの名前を知ってから、temp.zipに渡す必要がありますunzip

それはの出力をリダイレクトすることが可能であるwgetunzip?何かのようなもの

$ unzip < `wget http://www.vim.org/scripts/download_script.php?src_id=11834`

しかし、うまくいきませんでした。

bash::wget http://www.vim.org/scripts/download_script.php?src_id=11834 -O temp.zipあいまいなリダイレクト

また、wget2回実行され、ファイルを2回ダウンロードしました。


後者の例では、?はシェル内の特殊文字です。URLを「」に入れると役立ちます。
p-static

このスレッドには解決策があるようです。自分で試したことはありません。serverfault.com/questions/26474/...

回答:


96

次の理由により、ファイルを一時ファイルにダウンロードする必要があります(unzip manページを引用):

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

コマンドをまとめるだけです:

wget http://www.vim.org/scripts/download_script.php?src_id=11834 -O temp.zip; unzip temp.zip; rm temp.zip

しかし、より柔軟にするために、おそらくスクリプトに入れて入力を節約し、誤って何かを上書きしないようにするために、mktempコマンドを使用して一時ファイルの安全なファイル名を作成できます:

#!/bin/bash
TMPFILE=`mktemp`
PWD=`pwd`
wget "$1" -O $TMPFILE
unzip -d $PWD $TMPFILE
rm $TMPFILE

であるwget file.zip && unzip file.zipと同じwget file.zip; unzip file.zipか一方が他方よりも優先されますか?ありがとう:)
jaggedsoft 16

7
@NextLocal wget && unzipは、wgetが成功した場合にのみ解凍を実行します。wget ; unzipとにかくunzipを実行し、存在しないファイルを指している可能性があります。
手本

funzipは私が探していた答えでした。Terraformは(何らかの理由で)zipアーカイブ内の単一のファイルとしてバイナリであるため、これは私にとって完璧でした。
Asfand Qazi

74

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

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

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

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

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

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

1
これは素晴らしいです!tarを使用すると、非圧縮データのサイズが間違っている(0が予期される)ことについて警告が表示されますが、ファイル自体は破損していないように見えます。これを推測するのは、インデックスがないためです。
Wyatt8740

1
私が持っている.zip実行権限を持つファイルが含まれてここに-fileを。をダウンロードしてにパイプするbsdtarと、execビットが破棄されます。ディスクにダウンロードしてから、bsdtarまたはunzipそれ以降で抽出すると、execビットが尊重されます。
ゴラーランブラー

//、@ GolarRamblar、理由を見つけたことがありますか?
ネイサンバサニーズ

1
@NathanBasanese:ここに答えがあります。要するに、ZIPアーカイブにはそのような情報を格納する2つの場所があり、それらは一貫性がなく、ファイルをbsdtar開くことがシーク可能かどうかに応じて、どちらか一方の場所を使用します。
ゴラーランブラー

20

JDKがインストールされている場合は、次を使用できますjar

wget -qO- http://example.org/file.zip | jar xvf /dev/stdin

3
jarファイルのアクセス許可が保持されないことがわかりました。それ以外の場合はすてきなトリック。
プネヘヘ16

7
ファイル| jar xv
パラメーター

15

wgetの出力をunzipにパイピングする必要さえないと思います。

ウィキペディアの「ZIP(ファイル形式)」記事から:

ZIPファイルは、ファイルの最後にある中央ディレクトリの存在によって識別されます。

wzipは、unzipが作業を行う前にダウンロードを完全に終了する必要があるため、考えられるように織り交ぜることなく、順次実行されます。


10

適切な構文は次のとおりです。

$ unzip <(curl -sL https://www.winpcap.org/archive/1.0-docs.zip)

しかし、それはエラーが原因(のため、動作しませんのInfo-ZIPのDebian):

lseek(3, 0, SEEK_SET)                   = -1 ESPIPE (Illegal seek)

Archive:  /dev/fd/63
  End-of-central-directory signature not found.  Either this file is not
  a zipfile, or it constitutes one disk of a multi-part archive.  In the
  latter case the central directory and zipfile comment will be found on
  the last disk(s) of this archive.
unzip:  cannot find zipfile directory in one of /dev/fd/63 or
        /dev/fd/63.zip, and cannot find /dev/fd/63.ZIP, period.

またはBSD / OS Xの場合:

Trying to read large file (> 2 GiB) without large file support

これは、標準のzipツールが主にlseekfunctionを使用して、中央ディレクトリレコードの末尾を読み取るために、最後にファイルオフセットを設定するためです。アーカイブ構造の最後にあり、ファイルのリストを読み取る必要があります(Zipファイル形式構造を参照)。したがって、入力オブジェクトをlseek関数で配置できないため、ファイルをFIFO、パイプ、端末デバイス、またはその他のダイナミックにすることはできません。

そのため、次の回避策があります。

  • 異なる種類の圧縮を使用する(例tar.gz
  • 2つの別個のコマンドを使用する必要があります。
  • 代替ツールを使用する(他の回答で提案されているように)、
  • 複数のコマンドを使用するエイリアスまたは関数を作成します。

まだFIFOである可能性があると思います。EOF(メモリまたは一時ファイルにFIFO全体を効果的にバッファリングする)までFIFOから読み取りを続ける必要があります。スクリプトの作成を容易にするために完全に実行可能ですが、あまり有用ではありません。
エヴァンキャロル

8

私の答えの再投稿:

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

これは非常にうまく機能します:

tar xvf <(curl -sL http://www.vim.org/scripts/download_script.php?src_id=11834)

jar xvf <(curl -sL http://www.vim.org/scripts/download_script.php?src_id=11834)

wget -qO- http://www.vim.org/scripts/download_script.php?src_id=11834 | tar xvf -

wget -qO- http://www.vim.org/scripts/download_script.php?src_id=11834 | jar xvf -
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.