解压缩通过管道飞入的文件

Ale*_*lex 47 linux ubuntu compression pipe

我可以让 unzip 或任何类似的程序在标准输出上工作吗?情况是我正在下载一个 zip 文件,该文件应该可以即时解压缩。

相关问题:如何将下载的文件通过管道传输到 bash 中的标准输出?

Jas*_*mbs 24

虽然 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)
Run Code Online (Sandbox Code Playgroud)

此脚本可以缩小到一行并创建为别名。

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 '.')\""
Run Code Online (Sandbox Code Playgroud)

现在轻松解压缩 wget 的输出。

wget http://your.domain.com/your/file.zip -O - | unzip-stdin target_dir
Run Code Online (Sandbox Code Playgroud)

  • 很好的单行,+1 提到文件必须适合内存。(不幸的是,由于文件格式结构,无法解压缩 pkzip 文件)。 (5认同)
  • 请记住,这会在提取之前缓冲内存中的所有内容 (3认同)
  • 这是**不是**流,您正在使用`.read()`方法读取内存中的整个文件 (3认同)

Dav*_*ley 18

这不太可能像您期望的那样工作。Zip 不仅是一种压缩格式,还是一种容器格式。它将 tar 和 gzip.bzip2 的作业合二为一。话虽如此,如果您的 zip 文件只有一个文件,您可以使用 unzip -p 将文件解压缩到标准输出。如果您有多个文件,您将无法分辨它们的起点和终点。

至于从标准输入读取,解压手册页有这句话:

尚不支持从标准输入读取的档案,除了 funzip(然后只能提取档案的第一个成员)。

您可能对 funzip 有一些运气。


小智 10

我喜欢使用 curl 因为它是默认安装的(-L经常发生的重定向需要它):

curl -L http://example.com/file.zip | bsdtar -xvf - -C /path/to/directory/
Run Code Online (Sandbox Code Playgroud)

但是,bsdtar默认情况下未安装,我无法开始funzip工作。


小智 9

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

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

当尝试通过管道读取 ZIP 存档时,这似乎会造成问题,因为直到最后才访问索引,因此在文件完全读取并且不再可用之前无法正确提取单个成员. 因此,当通过管道提供存档时,大多数 ZIP 解压缩器只会失败,这似乎并不奇怪。

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

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

wget -qO- http://example.org/file.zip | bsdtar -xvf-
Run Code Online (Sandbox Code Playgroud)


nik*_*nik 8

您想要做的是, makeunzip在其标准输入上采用 ZIP 压缩文件,而不是作为参数。这通常是很容易支持gziptar样带工具-的说法。但是标准unzip并没有这样做(尽管它确实支持提取到管道)。然而,一切都没有丢失......

查看funzip手册页。

没有文件参数的 funzip 充当过滤器;也就是说,它假定 ZIP 存档(或 gzip 文件)正在通过管道传输到标准输入中,并将第一个成员从存档中提取到标准输出。当 stdin 来自 tty 设备时,funzip 假定这不能是(二进制)压缩数据流,而是显示简短的帮助文本。如果有文件参数,则从指定文件而不是从标准输入读取输入。

鉴于对单个成员提取的限制,funzip 与辅助存档程序(例如 tar(1))结合使用最为有用。以下部分包括一个示例,说明在将磁盘备份到磁带的情况下的这种用法。

这与大多数 linux 档案通常经过 TAR 压缩,然后以某种方式(gzip、bzip 等)压缩的想法相吻合。如果您有tar.ZIP.


值得注意的funzip是,由Info-ZIP原作者Mark Adler撰写。他在 funzip 手册页中写道,

this functionality should be incorporated into unzip itself (future release).
Run Code Online (Sandbox Code Playgroud)

然而,没有看到这样的更新。我怀疑 Mark 认为没有必要,因为其他归档方法很容易与 TAR 配合使用。


小智 6

转贴我的回答

BusyBoxunzip可以使用标准输入并提取所有文件。

wget -qO- http://downloads.wordpress.org/plugin/akismet.2.5.3.zip | busybox unzip -
Run Code Online (Sandbox Code Playgroud)

后面的破折号unzip是使用 stdin 作为输入。

你甚至可以,

cat file.zip | busybox unzip -
Run Code Online (Sandbox Code Playgroud)

但这只是多余的unzip file.zip

如果您的发行版默认使用 BusyBox(例如 Alpine),只需运行unzip -.


小智 5

在 zsh 中,您可以执行以下操作:

unzip =( curl http://example.com/someZipFile.zip )
Run Code Online (Sandbox Code Playgroud)


Adr*_*ian 5

可以执行此操作的最简单的常用实用程序是jar,如果您不向它传递文件 args,它将假定正在使用 STDIN。它还需要类似于tar操作程序的参数。

例如列出档案的内容

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

虽然并不总是安装 Java,但在那些安装了 Java 的机器上,这jar绝对是最方便的方法。