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


74

当我使用

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)


提示:第一个命令还将打印名称与或匹配的目录*.js**.txt
通配符

Answers:


99
找 。-type f -name“ * .htm *” -o -name“ * .js *” -o -name“ * .txt”

的缩写:

找 。\(\(型的F -a -name “的* .htm *” \)-o \
          \(-name “* .js文件*” \)-o \
          \(- name“ * .txt” \)\
       \) -打印

也就是说,由于未指定任何动作谓词(仅指定condition),因此-print将为符合条件的文件隐式添加一个动作。

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

而:

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

的缩写:

找 。\(型的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"' {} \;

要么:

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

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


在某些sh -c用法中,您需要为sh添加第零个参数(尽管在其他情况下,您已经包含了它)。
James Youngman

1
这是一个很好的答案!
Marinos

30

它是暗含的括号。添加明确的括号。\( \)

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.