我之前编写了一个脚本,它在目录树中搜索 .h 和 .c 文件,然后在它们上运行 clang-format:
find $directory -name '*.[hc]' -exec clang-format -i {} \;
这正如预期的那样工作。现在我想将 .cpp 文件添加到搜索中。然而,既不
-name '*.{[hc],cpp}'
也不
-name '{*.[hc],*.cpp}'
工作。也就是说,他们找不到文件。
我知道如果我使用find
's-o
选项,我可以让我的逻辑工作。但是,必须有一种方法可以使用单个-name
指令来执行此操作。
与
-name
谓词一起使用的模式find
是标准文件名通配模式。您尝试使用的是find
不支持的大括号扩展。请注意,没有一个
.c
标准的通配模式可以匹配以,.h
或结尾的文件名.cpp
。您可能想使用类似
'*.'{c,h,cpp}
, 扩展为*.c
,*.h
和 的东西*.cpp
,但不包括-name
谓词也不包括-o
.接下来要尝试的是
'-o -name "*.'{c,h,cpp}'"'
,但这会扩展到三个字符串-o -name "*.c"
-o -name "*.h"
,和-o -name "*.cpp"
。这也不能使用,因为您必须将它们拆分为空格才能find
识别单独的子字符串(并-o
从第一个子字符串中删除)。虽然它可能会起作用eval
,但它似乎比它的价值更麻烦。取而代之的是,您可以使用两个
-name
带有 OR 的测试:这使用了
-name
前面描述的两个测试(-o
是 OR 运算符),并且还clang-format
通过将找到的路径名批量传递给工具而不是为每个文件调用一次来尽可能少地调用。通过一点点额外的编程,您可以将要选择的所有文件名后缀存储在一个列表中,并
find
从中创建所需的表达式。由于您没有提及您正在使用什么外壳,我正在为 POSIX
sh
外壳执行此操作:或者
"$@"
在这个例子中展开的列表相当于-name
支持与 shell glob 不同的模式,但它不支持大括号(GNU find 手册页明确提及),也不支持 ksh 样式的扩展 glob。但是很多人都
find
支持-regex
,你也许可以使用它。根据您find
支持的正则表达式方言,标准的基本正则表达式不支持交替。使用 GNU find,这应该可以工作:
(另请注意,匹配与整个路径匹配,而不仅仅是文件名部分,但如果您只匹配文件名的最终后缀,那将不是问题。)