包含自己名字的文本文件

vik*_*kiv 4 find shell-script csh

我需要在某个目录及其所有子目录中找到包含自己名称的所有文本文件。我该怎么做呢?(最好没有 awk 命令)

Mic*_*mer 6

当文件名可能包含来自 的空格或其他字符时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的命令{},其中:

  • 为每个匹配的文件运行带有脚本命令字符串的标准 shell grep -lFe "$(basename "$1")" "$1",其中:
    • $1使用命令替换基本名称查找匹配文件 ( )的基本文件- 命令替换和变量都被引用以说明它们可能包含空格或通配符的情况;和
    • greps 该基名的匹配文件(仍为“ $1”),用于-l仅打印匹配文件的名称。"$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循环,它查看每个文件。如果这是经常运行的东西,这是比使用“ ;”来终止命令更好的选择。