如何将wget的输出作为输入重定向到解压缩?


131

我必须从此链接下载文件。下载的文件是一个zip文件,我必须将其解压缩到当前文件夹中。

通常,我会先下载它,然后运行unzip命令。

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

但是通过这种方式,我需要执行两个命令,等待第一个命令完成才能执行下一个命令,而且,我必须知道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::歧义重定向

另外,wget执行了两次,并下载了两次文件。


在后一个示例中,wget可能执行了两次,因为?是shell中的特殊字符。将网址放在“”中应该会有所帮助。
p静态

该线程似乎有解决方案。自己还没有尝试过。serverfault.com/questions/26474/...

Answers:


96

您必须将文件下载到临时文件,因为(引用解压缩手册页):

从标准输入中读取的存档,除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's

7
wget && unzip仅当wget成功时,@ NextLocal 才会运行解压缩。wget ; unzip无论如何将运行解压缩,可能指向不存在的文件。
temoto

funzip是我一直在寻找的答案。Terraform(出于某种原因)将二进制文件作为单个文件打包在zip压缩文件中,因此这对我来说是完美的。
阿斯凡德·卡兹

74

这是对类似问题的回答的转贴:

ZIP文件格式在存档末尾包含目录(索引)。该目录指出每个文件在档案中的位置,因此可以快速,随机地访问,而无需读取整个档案。

尝试通过管道读取ZIP归档文件时,这似乎造成了问题,因为直到最后才访问索引,因此只有在文件被完全读取并且不再可用后才能正确提取单个成员。 。因此,当通过管道提供归档文件时,大多数ZIP解压缩器只会失败就显得不足为奇了。

存档末尾的目录不是文件元信息存储在存档中的唯一位置。另外,出于冗余目的,各个条目还将此信息包含在本地文件头中。

尽管当索引不可用时,并不是每个ZIP解压缩器都将使用本地文件头,但是在通过管道读取时,libarchive(又名bsdtar和bsdcpio)的tar和cpio前端可以并且会这样做,这意味着可以进行以下操作:

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

1
太好了!我会注意到tar给我一些有关未压缩数据大小错误(预期为0)的警告,但文件本身似乎未损坏。猜测这是由于缺少索引。
Wyatt8740 '18

1
.zip这里有一个-file,其中包含具有可执行权限的文件。当我下载并输入时bsdtar,exec位会被丢弃。当我下载到磁盘并用bsdtarunzip进行解压缩时,将尊重exec位。
Golar Ramblar

//,@GolarRamblar,没有找到原因吗?
弥敦道(Nathan Basanese)

1
@NathanBasanese:是答案。简而言之:ZIP归档文件在两个位置存储了此类信息,这可能是不一致的,并且取决于是否可以bsdtar打开文件,它使用一个位置还是另一个位置。
Golar Ramblar

20

如果已安装JDK,则可以使用jar

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

3
我只是发现jar并没有保留文件权限。否则不错的把戏。
phunehehe

7
您无需提供文件参数,只需使用| jar xv
cricket_007

15

我认为您甚至都不需要将wget的输出管道解压缩。

来自维基百科的“ ZIP(文件格式)”文章:

ZIP文件通过位于文件末尾的中央目录来标识。

wget必须完全完成下载,然后解压缩才能执行任何工作,因此它们将按顺序运行,而不是像人们想象的那样交织在一起。


10

正确的语法为:

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

但是由于错误(Debian上的Info-ZIP)而无法正常工作:

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文件格式结构)。因此,该文件不能是FIFO,管道,终端设备或任何其他动态文件,因为该lseek功能无法定位输入对象。

因此,您有以下解决方法:

  • 使用不同类型的压缩(例如tar.gz),
  • 您必须使用两个单独的命令,
  • 使用其他工具(如其他答案中所述),
  • 创建别名或函数以使用多个命令。

我认为它仍然可以是FIFO。您只需要继续从FIFO读取直到EOF(有效地将整个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 -
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.