为什么找不到让我匹配多个模式?

Why doesn't find let me match multiple patterns?

我正在编写一些 bash/zsh 脚本来处理一些文件。我想对某个类型的每个文件执行一个命令,其中一些命令是重叠的。当我尝试 find -name 'pattern1' -or -name 'pattern2' 时,仅使用最后一个模式(不返回匹配 pattern1 的文件;仅返回匹配 pattern2 的文件)。我想要的是匹配 pattern1pattern2 的文件。

例如,当我尝试以下操作时,这就是我得到的(注意仅找到并打印 ./foo.xml):

$ ls -a
.        ..       bar.html foo.xml
$ tree .
.
├── bar.html
└── foo.xml

0 directories, 2 files
$ find . -name '*.html' -or -name '*.xml' -exec echo {} \;
./foo.xml
$ type find
find is an alias for noglob find
find is /usr/bin/find

使用 -o 而不是 -or 会得到相同的结果。如果我切换 -name 参数的顺序,则只返回 bar.html 而不是 foo.xml.

为什么找不到并返回 bar.htmlfoo.xml?如何匹配多个模式?

您需要在 find 命令中使用括号来对您的条件进行分组,否则只有第二个 -name 选项对 -exec 命令有效。

find . \( -name '*.html' -or -name '*.xml' \) -exec echo {} \;

寻找实用程序

-print == 默认值

如果你只想打印文件路径和名称,你必须删除 exec echo,因为 -print 是默认值。:

find . -name '*.html' -or -name '*.xml'

订单依赖性

否则,find从左到右阅读,参数顺序很重要!

因此,如果您想指定某些内容,请遵守 andor 优先级:

find . -name '*.html' -exec echo ">"{} \;  -o -name '*.xml' -exec echo "+"{} \;

find . -maxdepth 4 \( -name '*.html' -o -name '*.xml' \) -exec echo {} \;

表达式-print0xargs命令。

但是,在大多数情况下,您可以考虑使用 -print0 命令和 xargs 命令,例如:

find . \( -name '*.html' -o -name '*.xml' \) -print0 |
    xargs -0 printf -- "-- %s -\n"

这样做的好处是:

  • 只有一个(或少数)fork 找到了数千个条目。 (使用 -exec echo {} \; 意味着一个子进程是 运行 对于 找到的每个 条目,而 xargs 将构建一长行,其中包含一个命令行的参数可以容纳...)

  • 为了处理包含特殊字符或空格的文件名,-print0xargs -0 将使用 NULL 字符作为文件名分隔符。

查找...-exec...{}...+

几年前,find 命令接受 -exec 开关的新语法。

而不是 \;-exec 开关可以以加号 + 结尾。

find . \( -name '*.html' -o -name '*.xml' \) -exec printf -- "-- %s -\n" {} +

使用此语法,find 将像 xargs 命令一样工作,构建长命令行以减少分叉。