Alex Asked: 2009-06-17 04:32:52 +0800 CST2009-06-17 04:32:52 +0800 CST 2009-06-17 04:32:52 +0800 CST 解压缩通过管道飞入的文件 772 我可以让 unzip 或任何类似的程序在标准输出上工作吗?情况是我正在下载一个 zip 文件,它应该是即时解压缩的。 相关问题:如何将下载的文件通过管道传输到 bash 中的标准输出? linux ubuntu compression pipe 12 个回答 Voted Jason R. Coombs 2011-06-16T11:44:02+08:002011-06-16T11:44:02+08:00 虽然 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) 可以将此脚本缩小为一行并创建为别名。 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 David Pashley 2009-06-17T04:45:40+08:002009-06-17T04:45:40+08:00 这不太可能按您的预期工作。Zip 不仅是一种压缩格式,还是一种容器格式。它将 tar 和 gzip.bzip2 的工作合并为一个。话虽如此,如果您的 zip 文件只有一个文件,您可以使用 unzip -p 将文件提取到标准输出。如果您有多个文件,则无法确定它们的开始和停止位置。 至于从标准输入读取,解压缩手册页有这句话: 尚不支持从标准输入读取的档案,但 funzip 除外(然后只能提取档案的第一个成员)。 你可能对 funzip 有一些运气。 Todd Partridge 2016-03-06T07:47:33+08:002016-03-06T07:47:33+08:00 我喜欢使用 curl,因为它是默认安装的(-L经常发生的重定向需要它): curl -L http://example.com/file.zip | bsdtar -xvf - -C /path/to/directory/ 但是,bsdtar默认情况下没有安装,我无法开始funzip工作。 ruario 2014-04-17T09:54:30+08:002014-04-17T09:54:30+08:00 这是我对类似问题的回答的转贴: ZIP 文件格式包括存档末尾的目录(索引)。该目录说明每个文件在存档中的位置,因此允许快速、随机访问,而无需读取整个存档。 当尝试通过管道读取 ZIP 存档时,这似乎会造成问题,因为索引直到最后才被访问,因此在文件被完全读取并且不再可用之前无法正确提取单个成员. 因此,大多数 ZIP 解压缩器在通过管道提供存档时都会失败,这似乎不足为奇。 存档末尾的目录不是文件元信息存储在存档中的唯一位置。此外,出于冗余目的,各个条目还在本地文件头中包含此信息。 虽然不是每个 ZIP 解压缩器都会在索引不可用时使用本地文件头,但 libarchive(又名 bsdtar 和 bsdcpio)的 tar 和 cpio 前端可以并且将在通过管道读取时这样做,这意味着以下是可能的: wget -qO- http://example.org/file.zip | bsdtar -xvf- nik 2009-06-17T04:46:07+08:002009-06-17T04:46:07+08:00 您想要做的是,unzip在其标准输入上获取一个 ZIPped 文件,而不是作为参数。这通常很容易得到带有参数gzip的工具的支持。但是该标准并没有这样做(尽管它确实支持提取到管道)。然而,一切并没有丢失……tar-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). 但是,周围没有看到这样的更新。我怀疑 Mark 觉得没有必要,因为其他归档方法很容易与 TAR 配合使用。 Saftever 2018-10-12T04:13:09+08:002018-10-12T04:13:09+08:00 转发我的答案: BusyBoxunzip可以采用标准输入并提取所有文件。 wget -qO- http://downloads.wordpress.org/plugin/akismet.2.5.3.zip | busybox unzip - 后面的破折号unzip是使用标准输入作为输入。 你甚至可以, cat file.zip | busybox unzip - 但这只是多余的unzip file.zip。 如果您的发行版默认使用 BusyBox(例如 Alpine),只需运行unzip -. Adrian 2017-06-05T04:15:59+08:002017-06-05T04:15:59+08:00 可以执行此操作的最简单的常用实用程序是jar,如果您没有传递任何文件参数,它将假定正在使用 STDIN。它还接受类似于tar操作程序的参数。 例如列出档案的内容 curl https://my.example.com/file.zip | jar t 虽然并不总是安装 Java,但在安装了 Java 的机器上,这jar绝对是最方便的方法。 Dan Carley 2009-06-17T04:53:34+08:002009-06-17T04:53:34+08:00 Info-Zip 是最常见的 OSS 实现,这是不可能的。更重要的是,由于 ZIP 档案的结构,不建议这样做。 如果您可以更改格式,请考虑改用 tar(1)。它对流式输入/输出非常满意,事实上,默认情况下也期望它。 此外,您通常可以通过为文件名指定“-”来判断应用程序是否需要流式输入/输出。如您所想,Info-Zip 不会将此视为有效论点。 Ian Robertson 2013-11-15T14:09:57+08:002013-11-15T14:09:57+08:00 在 zsh 中,您可以执行以下操作: unzip =( curl http://example.com/someZipFile.zip ) SEoF 2013-11-14T10:01:14+08:002013-11-14T10:01:14+08:00 我实际上需要一些更复杂的东西——如果存在的话,提取一个特定的文件。困难在于,输入文件流可能不是 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 文件进行版本控制,其中文件可以是名为 workbench 文件的 xml 文件,也可以是完整的 workbench 文件。
虽然 zip 文件实际上是一种容器格式,但如果文件可以足够容易地放入内存,则没有理由不能从管道 (stdin) 中读取它。这是一个 Python 脚本,它将 zip 文件作为标准输入,并将内容提取到当前目录或指定目录(如果指定)。
可以将此脚本缩小为一行并创建为别名。
现在轻松解压缩 wget 的输出。
这不太可能按您的预期工作。Zip 不仅是一种压缩格式,还是一种容器格式。它将 tar 和 gzip.bzip2 的工作合并为一个。话虽如此,如果您的 zip 文件只有一个文件,您可以使用 unzip -p 将文件提取到标准输出。如果您有多个文件,则无法确定它们的开始和停止位置。
至于从标准输入读取,解压缩手册页有这句话:
你可能对 funzip 有一些运气。
我喜欢使用 curl,因为它是默认安装的(
-L
经常发生的重定向需要它):但是,
bsdtar
默认情况下没有安装,我无法开始funzip
工作。这是我对类似问题的回答的转贴:
ZIP 文件格式包括存档末尾的目录(索引)。该目录说明每个文件在存档中的位置,因此允许快速、随机访问,而无需读取整个存档。
当尝试通过管道读取 ZIP 存档时,这似乎会造成问题,因为索引直到最后才被访问,因此在文件被完全读取并且不再可用之前无法正确提取单个成员. 因此,大多数 ZIP 解压缩器在通过管道提供存档时都会失败,这似乎不足为奇。
存档末尾的目录不是文件元信息存储在存档中的唯一位置。此外,出于冗余目的,各个条目还在本地文件头中包含此信息。
虽然不是每个 ZIP 解压缩器都会在索引不可用时使用本地文件头,但 libarchive(又名 bsdtar 和 bsdcpio)的 tar 和 cpio 前端可以并且将在通过管道读取时这样做,这意味着以下是可能的:
您想要做的是,
unzip
在其标准输入上获取一个 ZIPped 文件,而不是作为参数。这通常很容易得到带有参数gzip
的工具的支持。但是该标准并没有这样做(尽管它确实支持提取到管道)。然而,一切并没有丢失……tar
-
unzip
查看funzip手册页。
这与大多数 linux 档案通常经过 TAR 压缩然后以某种方式压缩(gzip、bzip 等)的想法相吻合。如果您有
tar.ZIP
.值得注意的
funzip
是,由 Info-ZIP 原作者 Mark Adler 撰写。他在 funzip 手册页中写道,但是,周围没有看到这样的更新。我怀疑 Mark 觉得没有必要,因为其他归档方法很容易与 TAR 配合使用。
转发我的答案:
BusyBox
unzip
可以采用标准输入并提取所有文件。后面的破折号
unzip
是使用标准输入作为输入。你甚至可以,
但这只是多余的
unzip file.zip
。如果您的发行版默认使用 BusyBox(例如 Alpine),只需运行
unzip -
.可以执行此操作的最简单的常用实用程序是
jar
,如果您没有传递任何文件参数,它将假定正在使用 STDIN。它还接受类似于tar
操作程序的参数。例如列出档案的内容
curl https://my.example.com/file.zip | jar t
虽然并不总是安装 Java,但在安装了 Java 的机器上,这
jar
绝对是最方便的方法。Info-Zip 是最常见的 OSS 实现,这是不可能的。更重要的是,由于 ZIP 档案的结构,不建议这样做。
如果您可以更改格式,请考虑改用 tar(1)。它对流式输入/输出非常满意,事实上,默认情况下也期望它。
此外,您通常可以通过为文件名指定“-”来判断应用程序是否需要流式输入/输出。如您所想,Info-Zip 不会将此视为有效论点。
在 zsh 中,您可以执行以下操作:
我实际上需要一些更复杂的东西——如果存在的话,提取一个特定的文件。困难在于,输入文件流可能不是 zip 文件,在这种情况下,我需要它继续通过管道。这是我的解决方案(主要感谢 Jason R. Coombs 解决方案)
我将它保存为我机器上“/bin”文件夹中名为“effpoptp”(不是简单名称)的文件,因此测试它是这样的:
目的是对 MySQL Workbench 文件进行版本控制,其中文件可以是名为 workbench 文件的 xml 文件,也可以是完整的 workbench 文件。