'find -exec' 如何用空格传递文件名?

Emm*_*maV 15 shell bash find quoting arguments

如果我有一个目录,其中包含一些名称有空格的文件,例如

$ ls -1 dir1
file 1
file 2
file 3
Run Code Online (Sandbox Code Playgroud)

我可以成功地将它们全部复制到另一个目录,如下所示:

$ find dir1 -mindepth 1 -exec cp -t dir2 {} +
Run Code Online (Sandbox Code Playgroud)

但是,输出find dir1 -mindepth 1包含未转义的空格:

$ find dir1 mindepth 1
dir1/file 1
dir1/file 3
dir1/file 3
Run Code Online (Sandbox Code Playgroud)

如果我使用print0而不是print,输出仍然包含未转义的空格:

$ find dir1 mindepth 1 -print0
dir1/file 1dir1/file 2dir1/file 3
Run Code Online (Sandbox Code Playgroud)

要使用 手动复制这些文件cp,我需要对空格进行转义;但是当cp的参数来自时,这似乎是不必要的find,无论我是否使用+\;在命令末尾。

这是什么原因?

Rob*_*rtL 9

find命令直接执行该命令。该命令,包括文件名参数,将不会被 shell 或任何其他可能修改文件名的东西处理。这是非常安全的。

您是正确的,无需转义命令行{}上由 表示的文件名find

find将原始文件名从磁盘直接传递到-exec命令的内部参数列表中,在您的情况下,是cp命令。

  • linux 俱乐部的第一条规则是你不要解析 ls (3认同)
  • 简而言之,“find..exec”可以自己处理奇怪的文件名。 (2认同)

Tho*_*key 5

问题分为两部分:

  • 如何在 遇到文件名中嵌入空格的问题的情况下find设法调用程序-exec,以及
  • 有什么好处-print0

首先,find是进行系统调用,实际上是一组称为"exec"的相关调用中的一个。它将文件名作为参数直接传递给此调用,然后直接传递(在创建新进程之后)而不会丢失有关文件名的信息。

POSIXfind功能+原理中解释如下:

SVR4find实用程序的一个特点是-exec主要的 + 终止符。这允许将包含特殊字符(尤其是换行符)的文件名组合在一起,而不会出现将此类文件名通过管道传输到xargs. 其他实现添加了其他方法来解决此问题,特别是-print0使用空字节终止符写入文件名的主要方法。此处考虑过,但未采用。使用空终止符意味着任何要处理 find-print0输出的实用程序 都必须添加一个新选项来解析它现在将读取的空终止符。

特别-print0主要的”指的是 GNU findxargs它以不同的方式解决问题。FreeBSDfindxargs. 如果您在调用中添加了一个-0选项(请参阅手册页xargs,则该程序接受以“空字节”字符结尾的行。反过来,xargs调用exec -functions 来完成它的工作。-print0and-0特性与+特性之间的主要区别在于,前者通过管道传递文件名,而后者则不然。开发人员可以找到几乎所有功能的用途;管道也不例外。

回到 OP 的例子,它使用了一个-t选项cp:在POSIX cp 中找不到。相反,它是GNU cp提供的扩展(又名“非标准功能”)。的-0扩展xargs不会改进这个例子,但在其他情况下它可以有效地使用——记住有可移植的替代品+,GNUfind接受。