卷曲到焦油用管子拉链

时间:2014-09-15 15:31:02

标签: bash curl zip tar

我想下载一个tar.gz存档,将其解压缩并在一个带有bash脚本的命令中将其压缩为zip文件。原因是与临时文件无关。

我使用的代码:

curl -L "someURL" | tar xOz --strip-components=1 | zip -@ test.zip

向STDOUT提供了大量输出,因此我猜zip不接受管道。

也许我在这里遗漏了一些东西,但是zip的手册页并没有给我提供比使用-@-更多的信息,也没有互联网。

2 个答案:

答案 0 :(得分:3)

zip的联机帮助页(至少在我的系统上)说:

  

如果文件列表指定为 - @ [Not on MacOS],zip将从标准输入而不是命令行获取输入文件列表。例如,
   zip -@ foo
  将在foo.zip中的stdin上每行列出一个文件。

tar

的联构帮助页面
  

-O, --to-stdout
  将文件提取到标准输出。

简而言之:

tar -O可以在一个长流中将文件(但不是其名称)输出到stdout。但是zip需要stdin上的文件名列表。所以这不会起作用。并且很难看到如何使它工作,因为bash管道只是非结构化的字符串,但是要将信息从tar传输到zip,你需要添加一些结构,即使它是最小的:

[filename][filedata][filename][filedata]...

发件人(tar)和接收者(zip)必须就该结构的格式达成一致。哪个不会发生。

但是,您可以使用除命令行实用程序之外的tarzip接口。例如,如果安装了python,则以下内容应该有效:

#!/usr/bin/python
import sys
import tarfile
import zipfile
tarf = tarfile.open(sys.argv[1], "r:*")
zipf = zipfile.ZipFile(sys.argv[2], "w", zipfile.ZIP_DEFLATED)
for m in tarf:
  if m.isreg():
    zipf.writestr(m.path, tarf.extractfile(m).read())

(需要进行大量错误检查。如上所述,它只会在出现任何错误时崩溃。)

你可以把它变成一个“非常长的”一个shell,虽然我个人只是使​​用上面的python脚本。

 python -c "$(printf %s \
   'import sys;import tarfile;import zipfile;' \
   'T=tarfile.open(sys.argv[1],"r:*")' \
   'Z=zipfile.ZipFile(sys.argv[2],"w",zipfile.ZIP_DEFLATED);' \
   '[Z.writestr(m.path,T.extractfile(m).read()) for m in T if m.isreg()]')" \
   input.tar output.zip

(如果你想从curl管道进入,请使用/dev/stdin作为输入文件。我认为会避免Python试图将stdin解释为UTF- 8流。)

答案 1 :(得分:2)

tar将把所有文件数据发送到stdout(但没有文件名)。

zip可能不会对此产生任何影响(除非在单个zip文件中创建所有文件内容的巨大拉链,我无法想象你想要那样)。 / p>

如果要创建文件的zip存档,则需要将文件解压缩到磁盘。

我打算说你可以循环遍历tarball中的条目(按名称)并将每个条目提取到管道(尽管就扫描所需的次数而言,这将是非常昂贵的。 tarball)但我实际上并没有看到,至少在这里有zip的手册页,有一种方法可以通过标准输入来压缩压缩数据。它似乎只是采用文件名。