为什么这不能将我的所有文件解压到给定目录中?

t95*_*950 12 linux bash

为什么这不能解压给定目录中的所有 zip 文件?

find -name "*.zip" -exec unzip {} + \;
Run Code Online (Sandbox Code Playgroud)

相反,对于每个匹配项,我得到“警告:文件名不匹配:”

Kam*_*ski 28

分析

\n
\n
find -name "*.zip" -exec unzip {} + \\;\n
Run Code Online (Sandbox Code Playgroud)\n
\n

这个命令本身在 级别上是无效的find,它甚至没有达到unzip运行的程度。-exec命令内的有效操作由或 由*find终止,而不是同时由两者终止。您的描述与 only 终止的操作的行为匹配,所以我假设这是您真正使用的命令:+\\;+

\n
find -name "*.zip" -exec unzip {} +   # still wrong\n
Run Code Online (Sandbox Code Playgroud)\n
\n

为什么这不能解压给定目录中的所有 zip 文件?

\n
\n

因为unzip只需要一个 zip 文件。附加操作数被解释为“要处理的归档成员”(请参阅man 1 unzip​​参考资料),即要从归档中提取的文件。通过使用,-exec unzip {} +您可以使用unzip来自 的扩展的可能多个参数进行调用{}。除第一个参数之外的所有参数都被解释为要处理的存档成员,但您不希望它们被如此对待。

\n
\n

* 严格来说:;. 中的反斜杠\\;只是为了; 在 shell 中转义,因此 shell 不会将其视为;命令终止符。shell 去掉了反斜杠并find看到;它应该的样子。

\n
\n

解决方案

\n

-exec unzip {} \\;代替使用。此形式将{}仅替换为一个路径名。它将产生unzip比原本更多的进程-exec unzip {} +,但每个进程unzip都会得到一个 zip 文件来处理,这正是该工具所期望的。

\n
find . -type f -name "*.zip" -exec unzip {} \\;\n
Run Code Online (Sandbox Code Playgroud)\n

我明确指定.为使答案可移植的起始路径。您find显然.默认使用,但某些实现需要find命令行中至少有一个路径。-type f以防某个目录(或套接字等)匹配-name "*.zip";一般来说可以。

\n
\n

例子

\n

想象一下,存在./foo.zip./bar.zip作为唯一的匹配文件。find -name "*.zip" -exec unzip {} +将执行:

\n
unzip ./foo.zip ./bar.zip\n
Run Code Online (Sandbox Code Playgroud)\n

(或者unzip ./bar.zip ./foo.zip)。该命令将尝试./bar.zip从中提取./foo.zip(或分别以相反的方式)。这不是你想做的。

\n

另一方面find -name "*.zip" -exec unzip {} \\;将执行:

\n
unzip ./foo.zip\nunzip ./bar.zip\n
Run Code Online (Sandbox Code Playgroud)\n

或同一对命令的相反顺序。这就是您想要做的。

\n
\n

笔记

\n

上例中的顺序没有指定。实际上这个答案基本上是正确的:

\n
\n

find将按照项目存储在目录条目中的顺序遍历目录树。[\xe2\x80\xa6]

\n
\n

理论上find不需要按照这个顺序遍历,只是碰巧这是一个方便实现的顺序。

\n

无论如何,在您的情况下,如果从一个 zip 中提取的文件与存储在另一个 zip 中的文件发生冲突,那么在某些时候unzip会询问您该怎么做。注意问题是关于什么档案的;不要假设任何特定的档案顺序。

\n