具有多个“-name”和“-exec”的“find”仅执行“-name”的最后匹配项

具有多个“-name”和“-exec”的“find”仅执行“-name”的最后匹配项

当我使用时

find . -type f -name "*.htm*" -o -name "*.js*" -o -name "*.txt"

它找到所有类型的文件。但是当我-exec在最后添加:

find . -type f -name "*.htm*" -o -name "*.js*" -o -name "*.txt" -exec sh -c 'echo "$0"' {} \;

看来它只打印.txt文件。我究竟做错了什么?

注意:使用 MINGW (Git Bash)

答案1

寻找 。 -type f -name "*.htm*" -o -name "*.js*" -o -name "*.txt"

是缩写:

寻找 。'('\
           '('-f型-A-名称“*.htm*”')'-o\
           '('-名称“*.js*”')'-o             \
           '('-名称“*.txt”')' \
       ')' -打印

也就是说,因为没有行动指定了谓词(仅状况),-print为符合条件的文件隐式添加一个操作。

(顺便说一句,这将打印非常规.js文件(-type f仅适用于.htm文件))。

尽管:

寻找 。 -名称“*.htm*”-o -名称“*.js*”-o -名称“*.txt”\
  -exec sh -c 'echo "$0"' {} \;

是缩写:

寻找 。'('-f型-A-名称“*.htm*”')'-o\
       '('-名称“*.js*”')'-o\
       '('-名称“*.txt”-A-exec sh -c 'echo "$0"' {} \;')'

对于find(就像许多语言一样),-a;省略时隐含)优先于或者( -o),并添加显式操作谓词(此处-exec)会取消-print上面看到的隐式操作。

在这里,您想要:

find . '(' -name "*.htm*" -o -name "*.js*" -o -name "*.txt" ')' \
       -type f \
       -exec sh -c 'echo "$0"' {} \;

或者:

find . '(' -name "*.htm*" -o -name "*.js*" -o -name "*.txt" ')' \
       -type f \
       -exec sh -c '
         for i do
           echo "$i"
         done' sh {} +

以避免sh每个文件运行一个。

-type f比它可能意味着从索引节点检索信息更昂贵-name,最好放在尽管某些find实现确实会在内部重新排序检查以进行优化)。

答案2

这是隐含的括号。添加明确的括号。\( \)

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -exec sh -c 'echo "$0"' {} \;

或使用 xargs (我喜欢 xargs,我发现它更容易,但显然不那么便携)。

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -print0 | xargs -0 -n1 echo

相关内容