找到“.git”目录,但忽略一些路径;或者“find -not”如何工作

找到“.git”目录,但忽略一些路径;或者“find -not”如何工作

我不明白 find -not 是如何工作的。

假设我想找到树中的所有 .git 目录。

find -type d -iname .git

没问题,但是假设我有一些我不喜欢包含的目录,有问题时它们可以称为“旧”和“备份”。

我可以通过管道发送到 grep -v ,这样就可以正常工作了。

find -type d -iname .git | grep -v old | grep -v backup

但是当我浏览 find 的手册页时,我注意到有一个 -not ,但我不知道它是如何工作的。

我这样尝试过,但他不排除旧目录。

find -type d -iname .git -not -iname old 

find-not 是如何工作的?我可以用它来发现问题吗?

答案1

find 处理这种情况有一点复杂:

如果表达式不包含除 之外的任何操作-prune-print则对表达式为 true 的所有文件执行。

因此,明确打印您想要的部分:

find -type d \( -iname old -prune -o -iname backup -prune -o -iname .git -print \)

完全避免搜索旧树和备用树。

答案2

您可以通过指定排除目录-path

find . -type d \( -iname .git ! -path "*/old/*" ! -path "*/backup/*" \)

请注意,-not在 GNU 中find与 POSIX 相同,!但不兼容。

引用自man find

   ! expr True  if  expr  is false.  This character will also usually need
          protection from interpretation by the shell.

   -not expr
          Same as ! expr, but not POSIX compliant.

答案3

你需要-prune选择find,这真的很棘手。它需要使用too-path来代替-name

我想你想用这个:

find . -type d \( -path '*/old' -prune -o -iname '.git' -print \)

的效果-not是通过

  • 匹配旧的“旧”,而donig什么也没有
  • 或(使用选项 -o)
  • 匹配“.git”并打印名称
  • 或(默认)
  • 不执行任何操作(因为 find 的正常默认操作(-print命令行末尾的隐式操作)已被禁用(如果-print已使用)

我认识到其他变体,同时看着命令行上更复杂,可能更容易使用,例如因为使用了不同的逻辑表达式,以及默认操作的更改。
另一方面,-prune当其他语法因为太长而难以阅读时,涉及的变体更容易泛化到更复杂的情况。

答案4

find -type d -iname .git -not -iname old 

这匹配被调用.git和未被调用的目录old。由于.git无法调用被调用的目录old,因此可以删除该-not -iname old部分而不改变命令的含义。

-not说“不匹配”,但不是“不递归”。有一种不同的方式来表达“不要递归”:这是一个名为 的操作-prune。以下命令的意思是“递归遍历所有目录 ( find),但在名为old( -iname old -prune) 的目录处停止,并打印名为 ( ) 的目录.git”:

find -iname old -prune -o -type d -iname .git -print

这被解析为( -iname old -prune ) -o ( -type d -iname .git -print ). Find 的作用是查找满足条件-iname old或( -o) 的文件-type d -iname .git。当文件满足第一个条件时,-prune执行操作(从遍历的树中修剪,即不递归)。当文件满足第二个条件时,-print将执行该操作。由于打印是默认操作,因此您可以省略-print

相关内容