osx:有选择地压缩大量文件:-@选项可以吗?

osx:有选择地压缩大量文件:-@选项可以吗?

我需要创建一个 zip 文件,将包含约 500k 个文件的目录中的约 100k 个文件存档。当我尝试以下显而易见的命令时,我收到“参数列表太长”错误:

zip archive.zip *pattern*.txt                        # fails
zip archive.zip `find . -name "*pattern*.txt"`       # fails

一种方法是使用-@通过 stdin 传入文件列表的选项:

find . -name "*pattern*.txt" | zip -@ archive.zip

但是,zip手册页上写道:

如果文件列表指定为 -@ [不在 MacOS 上],则 zip 将从标准输入而不是命令行获取输入文件列表。

让我烦恼的是“不在 MacOS 上”这个选项。我继续尝试这个-@选项,它似乎有效;但我担心它是否真的能正常工作(完整地存档所有文件)。

以下是我的问题:

  1. 为什么-@在 MacOS 上不行?
  2. 在 MacOS/bash/zip 的某些版本中是否存在此警告,而在其他版本中是否存在此警告?这是一个过时的警告吗?如果是,那么分界线在哪里?
  3. 如果不使用的话,解决这个问题的可行方法是什么-@

请注意这里给出的解决方案zip:参数列表太长(总共 80,000 个文件)将不起作用;我需要存档目录中的部分文件,而不是全部文件。

我正在运行 Mac OS 10.7.5。以下是一些版本信息:

$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)
$ zip --version
This is Zip 3.0 (July 5th 2008), by Info-ZIP.
...
Compiled with gcc 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00) for Unix (Mac OS X) on Jun 24 2011.

答案1

首先,

zip archive.zip `find . -name "*pattern*.txt"`

绝不好主意。文件名可以包含空格、换行符、可以解释为开关的部分等等。

要对找到的每个文件执行操作,您可以使用-exec切换或参数

find . -name "*pattern*.txt" -exec zip archive.zip {} +

会将文件逐个添加到 zip 文件中。此处,{}表示当前正在处理的文件。

-exec用 a 来终止参数+;导致 find 同时处理多个文件(尽可能多的文件,而不会产生与您所遇到的相同的错误),这对于大量文件来说应该会快得多。

find . -name "*pattern*.txt" -print0 | xargs -0 zip archive.zip

本质上是一样的。xargs 默认一次处理多个文件。

切换-print0到 find 并-0切换到 xargs 使它们使用空字符作为文件分隔符,以正确处理奇怪的文件名。

我不知道为什么-@不推荐用于 Mac OS 1find ... | zip -@但是不是正确处理奇怪的文件名(具体来说,包含换行符的文件名)。无论使用哪种操作系统,这都是正确的。


1猜测这仅适用于 Mac OS 9.x 及以下版本,因为 Mac OS 使用回车符作为换行符,而zip -@需要换行符。

答案2

Dennis 是对的,这是 OS 9 的问题。我查看了 Zip 3.0 的源代码。在macos/平台目录中,有一条注释:

此移植适用于 Mac OS X 之前的 Mac 版本。由于 Mac OS X 是基于 Unix 构建的,因此请使用适用于 Mac OS X 的 Unix 移植。- 2008 年 6 月 7 日

此外,该zip.c文件将命令行选项的声明包装在 中#ifndef MACOS。换句话说,如果我运行 的“MacOS”端口zip,该-@选项就会失败。

丹尼斯还给出了“一种可行的方法来完成任务-@”的答案,即,

find . -name "*pattern*.txt" -print0 | xargs -0 zip archive.zip

我同意这是防止出现“奇怪”文件名(带有空格、换行符等的文件名)的最佳方法。但是,这会降低性能。 xargszip多次调用,每次都将一大组文件名作为命令行参数传递。 zip将在每次调用时将这些文件添加到其中archive.zip。但每次调用时zip都需要读取越来越大的文件archive.zip,随着作业的进展,这会花费越来越多的时间。

如果你知道一定所讨论的文件名不包含空格或换行符等病态字符,然后单次通过

find . -name "*pattern*.txt" | zip -@ archive.zip

会更快;而且它在 OS X 上工作得很好,因为zipOS X 实际上是 Unix 端口。手册页中的警告不适用。

答案3

正如您的版本信息所示,基础代码(因此文档可能也是如此)相当老旧,在此期间 MacOS 已经发生了很大变化。此外,构建版本比基础代码新得多,构建版本的代码/配置可能会发生更改,只是从未写入文档中。

无论如何,最好检查(也许用一个小例子)该命令是否有效,并且是否真正存储了它被要求存储的文件。如果这很重要,不要相信随机互联网网站上缺少部分的彩色方块……

相关内容