'find -exec'如何传递带有空格的文件名?


14

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

$ ls -1 dir1
file 1
file 2
file 3

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

$ find dir1 -mindepth 1 -exec cp -t dir2 {} +

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

$ find dir1 mindepth 1
dir1/file 1
dir1/file 3
dir1/file 3

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

$ find dir1 mindepth 1 -print0
dir1/file 1dir1/file 2dir1/file 3

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

这是什么原因呢?

Answers:


8

find命令直接执行命令。Shell或任何其他可能修改文件名的命令将不会处理该命令(包括filename参数)。非常安全

您是正确的,没有必要转义命令行{}上表示的文件名find

find将磁盘中的原始文件名直接传递到-exec命令的内部参数列表(在本例中为cp命令)。


1
概括地说,find..exec可以自行处理..怪异的文件名
heemayl

2
Linux俱乐部的第一条规则是您不解析
l

5

问题分为两部分:

  • 如何 find设法调用程序使用-exec,而不会在问题嵌入在文件名空间,
  • -print0选项有什么好处?

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

POSIX的find功能+说明如下,在理由

SVR4 find实用程序的一个功能是-exec主服务器的+终结器。这样就可以将包含特殊字符(特别是换行符)的文件名组合在一起,而不会出现将这些文件名传递到的问题xargs。其他实现还添加了其他方法来解决此问题,特别是-print0使用空字节终止符写入文件名的主数据库。这里考虑了这一点,但没有采纳。使用空终止符意味着要处理find的-print0输出的任何实用程序 都必须添加一个新选项来解析现在将要读取的空终止符。

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

回到OP的示例,该示例使用一个-t选项cp:在POSIX cp中找不到。而是它是GNU cp提供的扩展(也称为“非标准功能”)。该-0扩展xargs不会提高这个例子,但也有它可以用来记有效保管,有便携其他选择的情况下+,这GNU find接受。


-1

这应该是评论,但太大了。

对于那些喜欢尝试的人:

创建一个脚本,列出传入的位置参数,将其称为list_positional_parameters.sh

#!/bin/bash

# http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_07.html
# Try globbing patterns, e.g. "X[[:digit:]][[:digit:]]" to see what happens

if [ $# -lt 1 ]; then
   echo "Usage: $0 and then at least one parameter"
   exit 1
fi

counter=1

while (($#)); do
   echo "$counter = '$1'"
   # pop positional argument 1 off the stack of positional arguments
   shift
   (( counter++ ))
done

find在$ dir目录下运行它:

find "$dir" -exec ./list_positional_parameters.sh '{}' ';' | less

正如预期的那样,所有调用中只有一个参数,即文件名,无论其名称中是否有空格。


1
您也可以使用printflike printf '"%s"\n' "$@"打印所有引用的位置参数,以进行直观检查。
库沙兰丹
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.