使用 find 命令但排除两个目录中的文件

新手上路,请多包涵

我想查找以 _peaks.bed 结尾的文件,但排除 tmpscripts 文件夹中的文件。

我的命令是这样的:

  find . -type f \( -name "*_peaks.bed" ! -name "*tmp*" ! -name "*scripts*" \)

但它没有用。 tmpscript 文件夹中的文件仍会显示。

有人对此有想法吗?

原文由 Hanfei Sun 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 903
2 个回答

以下是您可以使用 find 指定的方法:

 find . -type f -name "*_peaks.bed" ! -path "./tmp/*" ! -path "./scripts/*"

解释:

  • find . - 从当前工作目录开始查找(默认递归)
  • -type f - 指定 find 您只希望结果中的文件
  • -name "*_peaks.bed" - 查找名称以 _peaks.bed
  • ! -path "./tmp/*" - 排除路径以 ./tmp/
  • ! -path "./scripts/*" - 同时排除路径以 ./scripts/ 开头的所有结果

测试解决方案:

 $ mkdir a b c d e
$ touch a/1 b/2 c/3 d/4 e/5 e/a e/b
$ find . -type f ! -path "./a/*" ! -path "./b/*"

./d/4
./c/3
./e/a
./e/b
./e/5

您非常接近, -name 选项仅考虑基本名称,其中 -path 考虑整个路径 =)

原文由 sampson-chen 发布,翻译遵循 CC BY-SA 3.0 许可协议

利用

find \( -path "./tmp" -o -path "./scripts" \) -prune -o  -name "*_peaks.bed" -print

或者

find \( -path "./tmp" -o -path "./scripts" \) -prune -false -o  -name "*_peaks.bed"

或者

find \( -path "./tmp" -path "./scripts" \) ! -prune -o  -name "*_peaks.bed"

顺序很重要。它从左到右评估。始终从路径排除开始。

解释

不要使用 -not (或 ! )排除整个目录。使用 -prune 。如手册中所述:

 −prune    The primary shall always evaluate as  true;  it
          shall  cause  find  not  to descend the current
          pathname if it is a directory.  If  the  −depth
          primary  is specified, the −prune primary shall
          have no effect.

并在 GNU 查找手册中:

 -path pattern
              [...]
              To ignore  a  whole
              directory  tree,  use  -prune rather than checking
              every file in the tree.

实际上,如果您使用 -not -path "./pathname" , find 将评估 "./pathname" 下每个节点的表达式。

find 表达式只是条件评估。

  • \( \) - 分组操作(你可以使用 -path "./tmp" -prune -o -path "./scripts" -prune -o ,但它更详细)。
  • -path "./script" -prune - 如果 -path 返回 true 并且是一个目录,则为该目录返回 true 并且 不要 进入该目录。
  • -path "./script" ! -prune - 它评估为 (-path "./script") AND (! -prune) 。它将修剪的“始终正确”恢复为始终错误。它避免打印 "./script" 作为匹配项。
  • -path "./script" -prune -false - 因为 -prune 总是返回 true,你可以跟随它 -false 做与 ! 339639d8fb78 相同的操作
  • -o - OR 运算符。如果两个表达式之间没有指定运算符,则默认为 AND 运算符。

因此, \( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print 扩展为:

 [ (-path "./tmp" OR -path "./script") AND -prune ] OR ( -name "*_peaks.bed" AND print )

打印在这里很重要,因为没有它会扩展到:

 { [ (-path "./tmp" OR -path "./script" )  AND -prune ]  OR (-name "*_peaks.bed" ) } AND print

-print 由 find 添加 - 这就是为什么大多数时候,您不需要在表达式中添加它。由于 -prune 返回 true,它将打印“./script”和“./tmp”。

在其他情况下没有必要,因为我们将 -prune 切换为始终返回 false。

提示:可以使用 find -D opt expr 2>&1 1>/dev/null 来查看它是如何优化和扩展的,

find -D search expr 2>&1 1>/dev/null 查看检查了哪个路径。

原文由 f380cedric 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏