使用find命令排除子目录

146

我有这样的目录结构

data
|___
   |
   abc
    |____incoming
   def
    |____incoming
    |____processed
   123
    |___incoming
   456
    |___incoming
    |___processed

在Data目录中的所有文件夹中,都有一个即将到来的子文件夹。我想从所有文件夹和子文件夹中获取所有文件,除了def/incoming和456/incoming目录。 我尝试使用以下命令:

 find /home/feeds/data -type d \( -name 'def/incoming' -o -name '456/incoming' -o -name arkona \) -prune -o -name '*.*' -print

但它并没有按预期工作。

Ravi


4
这并不是一个好的建议,但它可以让你快速且简单地摆脱很多困境:将其管道传输给grep -v something以排除任何你不想要的内容。 - Miquel
这个回答解决了你的问题吗?如何在find .命令中排除一个目录 - imz -- Ivan Zakharyaschev
6个回答

254

这个可以工作:

find /home/feeds/data -type f -not -path "*def/incoming*" -not -path "*456/incoming*"

解释:

  • find /home/feeds/data:从指定路径开始递归查找
  • -type f:仅查找文件
  • -not -path "*def/incoming*":不包括路径中包含def/incoming的任何内容
  • -not -path "*456/incoming*":不包括路径中包含456/incoming的任何内容

出现错误:"find: bad option -not find: path-list predicate-list"。 - Ravi
@Ravi,你使用的是bash shell吗?我刚在我的终端上测试过了,对我有效。如果你修改了脚本,请尝试复制和粘贴解决方案。 - sampson-chen
它正在工作,但是它列出的是那些目录中的目录而不是文件。 - Ravi
@Ravi 噢,抱歉——我搞混了你要找的东西。将“type d”更改为“-type f”,它会查找文件而不是目录(请参见更新后的答案)。 - sampson-chen
4
-path 匹配整个字符串,因此如果你使用 find . 命令进行查找,则 -path 参数后的字符串需要写成 ./path/to/directory/* 的形式。请注意不要改变原意,并使翻译更加通俗易懂。 - Heath Borders
4
FYI,-not -path 在这个例子中肯定有效,但是 find 仍然会迭代目录结构,并使用 CPU 周期来迭代所有这些目录/文件。为了防止 find 迭代这些目录/文件(可能有数百万个文件),则需要使用 -prune(但是 -prune 选项很难使用)。 - Trevor Boyd Smith

13

只是为了文档记录:你可能需要深入挖掘,因为有许多搜索和跳过组合(就像我一样)。结果可能会发现 prune 很有用,而 -not -path 不会达到你的期望效果。

所以这是一个有价值的例子,其中包括了15个排除目录的find命令示例:

http://www.theunixschool.com/2012/07/find-command-15-examples-to-exclude.html

要链接到最初的问题,对我来说,最终的排除方法如下:

find . -regex-type posix-extended -regex ".*def/incoming.*|.*456/incoming.*" -prune -o -print 

如果您想找到一个文件,但仍要排除路径,请添加 | grep myFile.txt

这也可能取决于您的“find”版本。我看到:

$ find -version
GNU find version 4.2.27
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX

1
在4.8.0版本中,不存在-regex-type选项,正确的选项是-regextype - undefined

5

-name 只匹配文件名,而不是整个路径。你需要使用 -path 来代替,在删除目录部分(例如def/incoming)时使用。


2
find $(INP_PATH} -type f -ls |grep -v "${INP_PATH}/.*/"

7
一些解释可能会让这个答案更好。 - Cris Luengo
感谢您提供这段代码片段,它可能会在短期内提供一些有限的帮助。通过展示为什么这是一个好的解决方案,适当的解释将极大地提高其长期价值,并使其对未来有类似问题的读者更有用。请编辑您的答案以添加一些解释,包括您所做的假设。 - Shawn C.
1
注意:如果使用find ... -print0与后面的xargs -0结合使用,则此技巧无效。 - phs

2

0
这是我排除所有 .git 目录并将其传递给 -exec 以在其中搜索某些内容的方法。
find . -not -path '*/\.*' -type f -exec grep "pattern" [] \;
  • -not -path '*/\.*' 将排除所有隐藏目录
  • -type f 仅列出文件类型,然后您可以将其传递给-exec或其他您想要执行的操作

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接