Unzip from Pipe

故事都有开始:

在寻找WordPressWooCommerce主题时,懒得去官网一个个看demo,想一次全部下载过来试用,于是有了下面的脚本:

i=0
while [ $((i++)) -lt 10 ]; do
        (curl -s "https://wordpress.org/themes/search.php?page=$i&q=woocommerce" | egrep -ow 'href="/themes/.+">' | cut -d\" -f2 | while read url; do
                (down=$(curl -s "https://wordpress.org"$url | egrep -ow '<p class="button">.*</p>' | cut -d\' -f2)
                wget http:$down) &
        done) &
done

但是一名偏执狂+强迫症患者+完美主义者是无法忍受不能一步到位的脚本滴,多一行代码都万分痛苦…


(一).然后就开始了漫漫谷歌路~

Archives read from standard input are not yet supported, except with funzip (and then only the first member of the archive can be extracted).

unzip manual页上(bug列表)上面有这句话,标准输入流中的压缩文档暂不支持解压,可以尝试使用funzip

@Ian Robertson介绍了一种在cshell下可用的方法(但在BASH下语法错误):

unzip =( wget -qO- http://downloads.wordpress.org/plugin/akismet.2.5.3.zip )

在这两个提问中,有一个共同的回答人@ruario:

The ZIP file format includes a directory (index) at the end of the archive. This directory says where, within the archive each file is located and thus allows for quick, random access, without reading the entire archive.

ZIP文件格式在文档的末尾都有一个目录结构(索引),这个索引指出压缩包中的每个文件位置在哪,以方便快速随机访问,而无需读取整个包。

This would appear to pose a problem when attempting to read a ZIP archive through a pipe, in that the index is not accessed until the very end and so individual members cannot be correctly extracted until after the file has been entirely read and is no longer available. As such it appears unsurprising that most ZIP decompressors simply fail when the archive is supplied through a pipe.
这在读取ZIP流(管道)的时候会产生一个问题,除非这个文件流被完整的读取,否则你无法正确的执行解压,因为这个索引在流的末尾从而一开始无法获取到。就因为这个原因导致大部分解压工具直接从管道解压的话会失败。
The directory at the end of the archive is not the only location where file meta information is stored in the archive. In addition, individual entries also include this information in a local file header, for redundancy purposes.
包的尾部并不是这个文件元数据信息存储的唯一位置。实际上,每一个单独的个体都会在文件头中包含这些信息,以防止包损坏从而无法读取整个文件?
Although not every ZIP decompressor will use local file headers when the index is unavailable, the tar and cpio front ends to libarchive (a.k.a. bsdtar and bsdcpio) can and will do so when reading through a pipe.

并不是每一个压缩工具都会去利用这个单独的文件头来获取索引(即unzip只会读取压缩包末尾的索引,而忽略每一个单独条目的头部信息?)

但还是有一些基于libarchive的tar和cpio工具例如bsdtar、bsdcpio支持从管道读取压缩文件:

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


(二).BSDtar到底是什么?

安装bsdtar-2.8.4-14.7.6.x86_64.rpm,不同的系统版本对应不同的包,均可在rpm.pbone.net找到。

(bsdtar依赖libarchive2>=2.8.4,如果系统未安装的话需先装libarchive2-2.8.4-9.3.x86_64.rpm

听说osc没法上传附件,那就用图片来代替吧: -。- || 将左边的表情另存为1.rar解压即可得到bsdtar的rpm包,生成命令如下:

copy /B 1.gif+1.rar 2.gif

安装后即可使用bsdtar和bsdcpio,试用效果不错,看help还支持lzma压缩,唯一的缺陷是解压后的文件及目录都变成了所有者权限777…

如果想了解bsdtar和GUN tar的区别可以看这个问题:What are the differences between bsdtar and GNU tar?

作者挺幽默,说他还提过另一个问题:What are the main differences between BSD and GNU/Linux userland?

GNUtar does support the other tar variants and automatic compression detection.
GNUtar支持其他tar的变体,并且可以自动识别压缩格式。


(三).当然如果你乐意用python的话…

import zipfile, sys, StringIO
data = StringIO.StringIO(sys.stdin.read())
z = zipfile.ZipFile(data)
dest = sys.argv[1] if len(sys.argv) == 2 else '.'
z.extractall(dest)

可以将这段代码(参考末尾链接)写到一个文件unzip.py,然后执行以下命令:

alias unzip-stream="python unzip.py"
wget http://your.domain.com/your/file.zip -O - | unzip-stream target_dir

这种方式的确有点“笨”。


(四).再来看看前文提到的funzip:

curl -s http://example.org/file.zip | funzip > result

通过funzip我们可以一步到位解压网上的zip文件,但这仅限于只包含一个条目的zip压缩包。 bug列表上写的很清楚:

There is presently no way to extract any member but the first from a ZIP archive. This would be useful in the case where a ZIP archive is included within another archive. In the case where the first member is a directory, funzip simply creates the directory and exits.

funzip目前没有办法解压压缩包中的所有文件,所以funzip只可用于对再压缩的包进行解压。。类似file.tar.zip。

否则若包的第一个成员是目录的话,funzip会创建这个目录,然后退出……

这样看来,funzip其实也意义不大,难道就没有更好的办法了???


附录:批量解压的各种写法

ls *.zip | xargs unzip
#
ls *.zip | while read f; do
        unzip $f
done
#
for f in *.zip; do
        unzip $f
done
#
echo *.zip | xargs -l unzip
#
find . -name '*.zip' -exec unzip {} \;


参考funzip ubuntu manualPipe unzip to ddhow to use unzip with pipe


P.S.后来我发现这个@ruario简直是无处不在,github上也看到了他的身影:wgunpack.sh

还有这里:Unzipping files that are flying in through a pipe


转载于:https://my.oschina.net/cwalet/blog/318682

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值