带有多个 `-name` 和 `-exec` 的 `find` 只执行 `-name` 的最后一个匹配项

jak*_*b.g 96 find

当我使用

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)

Sté*_*las 130

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

简称:

找 。'(' '(' -type f -a -name "*.htm*" ')' -o \
           '(' -name "*.js*" ')' -o \
           '(' -name "*.txt" ')' \
       ')' -打印

也就是说,因为没有指定动作谓词(只有conditions),所以-print为匹配条件的文件隐式添加了一个动作。

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

尽管:

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

简称:

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

对于find(就像在许多语言中一样),AND-a省略时隐式)优先于OR-o),并且添加显式动作谓词(此处-exec)取消了-print上面看到的隐式动作。在这里,你想要:

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

或者:

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

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

  • 这是一个很好的答案! (2认同)

ctr*_*lor 30

它是隐含的括号。添加显式括号。\( \)

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

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

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