当文件名可能包含来自 的空格或其他字符时IFS,为了最大程度地可移植和工作,并且在find不处理{}内部引号的系统上,与普通参数传递find -exec结合使用sh:
find DIRECTORY -type f -exec sh -c 'grep -lFe "$(basename "$1")" "$1"' sh {} ';'
Run Code Online (Sandbox Code Playgroud)
find DIRECTORY -type fDIRECTORY递归枚举所有普通文件。-exec ... ';'为它找到的每个文件运行一个命令。它的主要内容是sh通过 to的命令{},其中:
grep -lFe "$(basename "$1")" "$1",其中:
sh:“ sh”和{}。sh用于内联脚本$0(正在运行的程序的名称,例如 shell 用于错误报告)。find将{}使用匹配的文件名替换完全由 组成的参数,因此sh脚本本身获得一个参数,其中完整的文件路径可用$1.这将适用于任何兼容 POSIX 的系统。使用{}带引号的字符串内find -exec 具有实现定义的行为,因此是不可移植的(虽然它是由GNU支持grep和大多数BSD系统),并作为文件名被解释为危险的shell代码。
当任意文件名可能包含空格、通配符或IFS输入字段分隔符变量的值未知时,它们总是需要引用;否则它们将被拆分成多个单词并使程序以意想不到的方式运行。
更有效地,您可以使用find -execwith+来运行尽可能少的 shell:
find DIRECTORY -type f -exec sh -c 'for x in "$@" ; do grep -lFe "$(basename "$x")" "$x" ; done' sh {} '+'
Run Code Online (Sandbox Code Playgroud)
这仍然是可移植的,但为每次执行提供了许多文件路径sh,因此它不会启动那么多的 shell。shell 程序内部是一个for循环,它查看每个文件。如果这是经常运行的东西,这是比使用“ ;”来终止命令更好的选择。