【问题标题】:How do you specify filenames within a zip when creating it on the command line from a pipe?从管道在命令行上创建压缩包时,如何在压缩包中指定文件名?
【发布时间】:2011-01-02 10:33:03
【问题描述】:

我正在尝试从正在输入的文件内容创建一个 zip 文件,例如

mysql [params and query] | zip -q output.zip -

这会正确写入 zip,但是当您打开 zip 时,其中的文件称为“-”。有什么方法可以指定输入数据的文件名应该在 zip 中吗?

【问题讨论】:

  • 请不要将问题标记为“属于超级用户”(或属于其他任何地方) - 只需投票移动它们即可。
  • @Neil 完全同意你的看法!

标签: linux zip stdin pipe


【解决方案1】:
mysql [params and query] | python3 -c "import sys as s,os,zipfile as m;z=m.ZipFile(os.fdopen(s.stdout.fileno(),'wb'),'w');z.writestr(s.argv[1],s.stdin.read());z.close()" 'filename.sql' > output.zip

Python 3.5 增加了对不可搜索流的写入支持。

它不漂亮,但很有效。

【讨论】:

    【解决方案2】:

    你可以试试:

    mysql [params and query] | zip -q output.zip -@
    

    【讨论】:

    • 不,这不起作用,-@ 从标准输入中获取文件名列表,因此 mysql 的输出将被解释为文件列表。
    【解决方案3】:

    我无法使用PHP answer 进行管理(更大的 mysql 转储内存不足),并且 FIFO 没有按我的意愿工作,所以我的解决方案是在运行转储后重命名 ZIP 存档中的文件,使用 zipnote(它包含在 Debian 的 zip 包中)。

    mysql [params and query] | zip -q output.zip -
    echo -e "@ -\n@=newname.sql" | zipnote -w output.zip
    

    【讨论】:

    • 请注意zipnote 不会就地编辑文件,而是为每次调用创建一个新的临时文件。这可能是一个问题,您的存储介质没有足够的空间容纳两个这样大小的文件,或者如果您以这种方式添加大量文件并在执行过程中重命名每个文件(因此每次添加时都会重建整个存档)。
    【解决方案4】:

    据我所知,你不能同时使用zip 命令,我的意思是你不能同时指定文件名和管道内容。您可以通过管道传输内容,生成的文件是-,或者您可以使用-@ 管道传输文件名。

    这并不意味着使用其他技术不可能做到这一点。我概述了以下其中之一。这确实意味着您必须安装 PHP 并加载 zip 扩展。

    可能有很多其他方法可以做到这一点。但这是我所知道的最简单的。哦,它也是单行的。

    这是一个使用 PHP 的工作示例

    echo contents | php -r '$z = new ZipArchive();$z->open($argv[1],ZipArchive::CREATE);$z->addFromString($argv[2],file_get_contents("php://stdin"));$z->close();' test.zip testfile
    

    要在 Windows 上运行,只需交换单引号和双引号。或者只是将脚本放在一个文件中。

    “test.zip”是生成的 Zip 文件,“testfile”是通过管道传输到命令中的内容的名称。

    来自unzip -l test.zip的结果

    Archive:  test.zip
      Length      Date    Time    Name
    ---------  ---------- -----   ----
            6  01-07-2010 12:56   testfile
    ---------                     -------
            6                     1 file
    

    这是一个使用 python 的工作示例

    echo contents | python -c "import sys
    import zipfile
    z = zipfile.ZipFile(sys.argv[1],'w')
    z.writestr(sys.argv[2],sys.stdin.read())
    z.close()
    " test5.zip testfile2
    

    unzip -l的结果

    Archive:  test5.zip
      Length     Date   Time    Name
     --------    ----   ----    ----
            9  01-07-10 13:43   testfile2
     --------                   -------
            9                   1 file
    

    unzip -p的结果

    contents
    

    【讨论】:

    • 谢谢 - 试过了,效果很好!更喜欢这样做而不是保存到临时文件中。
    • @didier-trosset 的命名管道解决方案看起来更容易接受,因为它不需要整个编程语言 + 运行时。
    • @jc00ke 如果您愿意阅读 cmets,您将了解到命名管道解决方案也有缺点。我还用两种不同且非常常见的语言给出了这个例子。周围的大多数 Linux 系统都带有这两种运行时。还有一点是独立于平台的优势。
    • 整洁,但它似乎将整个文件读入内存,因此对于大文件可能是个问题。 @azenet 的解决方案避免了这种情况。
    【解决方案5】:

    您可以使用命名管道,并将请求输出发送给它,同时从它压缩。

    mkfifo output.txt ; mysql [params and query] > output.txt & zip output.zip -FI output.txt ; rm output.txt
    

    【讨论】:

    • 谢谢,这几乎有效:使用& zip会生成一个不完整的文件;似乎 zip 运行时尚未将所有数据刷新到命名管道中。如果我使用; zip 那就没问题了。
    • 使用; zip 的问题是它会等待mysql 命令完成后才开始从命名管道读取。命名管道没有无限容量。但是,如果内容不是很大,应该没有问题。
    【解决方案6】:

    你可以这样做。

    ls | zip test.zip -@
    

    这是因为我在目录中有 3 个文件。

    -rw-rw-r-- 1 xxx domain users   6 Jan  7 11:41 test1.txt
    -rw-rw-r-- 1 xxx domain users   6 Jan  7 11:41 test2.txt
    -rw-rw-r-- 1 xxx domain users   6 Jan  7 11:41 test3.txt
    

    和文件本身,结果是那么

    Archive:  test.zip
      Length     Date   Time    Name
     --------    ----   ----    ----
            6  01-07-10 11:41   test1.txt
            6  01-07-10 11:41   test2.txt
            6  01-07-10 11:41   test3.txt
     --------                   -------
           18                   3 files
    

    来自 Linux Zip Man 页面

    如果文件列表指定为-@, zip 获取输入文件的列表 来自标准输入。

    【讨论】:

    • 谢谢 - 当它有几个文件被管道输入时确实有效,但在这种情况下,我在文件的 contents 中管道(在这种情况下,制表符分隔 MySQL结果)。 Zip 足够聪明,可以将其视为一个文件,但我需要知道如何告诉它在它创建的 zip 文件中调用这些内容的内容。
    • 所以如果我理解正确的话,你想要 zipfile 中的 1 个文件,其中包含 sql 匹配的所有内容吗?
    • 这可能不是 OP 想要的,但这正是我所需要的 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-21
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多