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

and*_*nka 4 zip bash command-line macos

我需要制作一个 zip 文件,从包含 ~500k 文件的目录中归档 ~100k 文件。当我尝试明显的命令时,我收到“参数列表太长”错误:

zip archive.zip *pattern*.txt                        # fails
zip archive.zip `find . -name "*pattern*.txt"`       # fails
Run Code Online (Sandbox Code Playgroud)

一种方法是使用-@选项通过标准输入提供文件列表:

find . -name "*pattern*.txt" | zip -@ archive.zip
Run Code Online (Sandbox Code Playgroud)

但是,zip手册页说:

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

困扰我的是“不在 MacOS 上”。我继续尝试了这个-@选项,它似乎有效;但我对它是否真的在做正确的工作感到紧张(归档所有文件,完整无缺)。

以下是我的问题:

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

请注意,此处给出的解决方案zip: Argument list too long (80.000 files in total)将不起作用;我需要归档目录中的一些文件,而不是全部。

我正在运行 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.
Run Code Online (Sandbox Code Playgroud)

Den*_*nis 7

首先,

zip archive.zip `find . -name "*pattern*.txt"`
Run Code Online (Sandbox Code Playgroud)

从来没有一个好主意。文件名可以包含空格、换行符、可以解释为开关的部分等等。

要对每个找到的文件执行操作,您可以使用-execswitch 或xargs

find . -name "*pattern*.txt" -exec zip archive.zip {} +
Run Code Online (Sandbox Code Playgroud)

将文件一一添加到 zip 文件中。在这里,{}代表当前处理的文件。

-exec用 a终止参数+而不是;导致 find 一次处理多个文件(在不产生相同错误的情况下尽可能多地处理),对于大量文件来说,这应该会快得多。

find . -name "*pattern*.txt" -print0 | xargs -0 zip archive.zip
Run Code Online (Sandbox Code Playgroud)

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

-print0交换机找到和-0交换机xargs的让他们使用NULL字符作为文件分隔符与陌生文件名妥善处理。

我不知道为什么-@不建议适用于Mac OS 1,但find ... | zip -@不能正确地处理文件名怪(具体而言,包含文件名换行符)。无论操作系统如何,这都是正确的。


1这仅适用于版本 9.x 之前的 Mac OS,因为 Mac OS 使用回车符作为换行符,而zip -@期望换行符。