find 未能成功排除特定目录

find 未能成功排除特定目录

我想仅.git/使用find命令列出除目录内的文件之外的所有文件。

我试过这个:

$ find . -path .git -prune -type f
$

它返回了 0 个文件(而不是我有的 2 个),所以我尝试了这个:

$  find . -not -path .git -type f | grep -c '\.git'
1770
$

我不明白为什么这些都不起作用,你能帮忙吗?

EDIT0:感谢@icarus,我发现路径必须在前面,./并且我因此缺少OR运算符,此命令有效:

$ find . -path ./.git -prune -o -type f | grep '\.git'
./.git
./.gitignore
$

EDIT1:为什么其他命令不起作用?

$ find . -not -path ./.git -a -type f | grep -c '\.git'
1770
$

EDIT2:最后一个问题:为什么-prune谓词需要-o -print不打印以下命令中的./.gitand结果:./.gitignore

$ find . -name ".git*" -prune | grep git
./.git
./.gitignore
$ find . -name ".git*" -prune -o -print | grep -c git
0

编辑3:谢谢@rastafile:

$ find . -name ".git*" -prune | grep git
./.git
./.gitignore
$ find . -name ".git*" -prune -print | grep git
./.git
./.gitignore
$ find . -name ".git*" -prune -o -print | grep git
$

当前面的表达式为 true 时,GNU find 谓词似乎-prune会隐式调用:-print

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

结论:我需要的命令是:

$ find . -name ".git*" -prune -o -type f -print

谢谢大家。

答案1

-path和之间有很大的区别-name——它们一点也不相似:“名称”只查看最后一部分,“路径”查看整个斜杠链。 “文件名”或“路径名”的含义始终存在争议。但在这里,这一点是明确且重要的。

这有效(你说):

find . -path ./.git -prune -o -type f 

您从 开始.,因此会找到并修剪默认的 gitdir。不存在其他文件,因此检查./.git其他所有人 ( ) 的类型文件。-o


你的最后一个例子:

find . -not -path ./.git -a -type f 

不起作用,它只是找到所有文件

如果你想避免-prune,你必须匹配每个里面的条目:

-path './.git/*'

我同意 Icarus 的 -name/-prune 组合,但我有一个修改:

]# find . -name .git -prune -o -type f -name '*git*' -print   
./.git.filehidd
./gitfile

这里不需要括号。

即使-name '*git*'添加,用于测试/减少输出。

-print最后的显式操作通过修剪抑制打印:

]# find . -name .git -prune                                 
./.git
./10/.git

我对括号不太确定;我查了一下man find(GNU)并发现了关于它们的这个很好的细节:

 find . -name .snapshot -prune -o \( \! -name *~ -print0 \)

...,但省略名为 .snapshot 的文件和目录(以及其中的任何内容)。它还省略名称以 ~ 结尾的文件或目录,但不省略其内容。 这种结构-prune -o \( ... -print0 \) 很常见。 这里的想法是 -prune 之前的表达式匹配要修剪的内容。但是, -prune 操作本身返回 true,因此以下 -o 确保仅对那些未修剪的目录评估右侧(修剪目录的内容甚至没有被访问,因此它们的内容是不相关的) )。 -o 右侧的表达式是括号只是为了清楚起见。它强调 -print0 操作仅适用于未应用 -prune 的内容。因为测试之间默认的“and”条件绑定比 -o 更紧密,无论如何,这都是默认值,但括号有助于显示发生的情况。

对我来说,通过以下方式可以提高清晰度:

find . ( -name .snapshot -prune ) -o ( ! -name '*~' -print0 )

但这样是行不通的!

如果您在这里省略-a类似的内容,则-o足够突出,因此可以省略括号,也是为了清晰起见。


(因为 shell 也喜欢括号,你必须引用它们。但随后就告别了清晰度。)

1) find . -name .snapshot -prune -o \( \! -name *~ -print0 \)

2) find . -name .snapshot -prune -o ! -name '*~' -print0 

未加引号的!可以工作(我的可以),未加引号的则*不行。


因此,要查找除任何目录之外的文件(所有类型).git

find -name '.git' -type d -prune -o -print 

(如果你不在乎的话,类型 -d 也可以省略......请参阅卡米尔的评论……外面是丛林那里,发现是一个小编程语言: 你需要什么)

答案2

find 中连接项的默认操作是and这样的

find / -user root -name fred

表示查找既属于 root 又名为 fred 的文件。您想要执行一项or操作,如果它名为“.git”,则修剪它,或者如果它是一个文件,则列出它。

find . \( -name .git -prune \) -o -type f

请注意,我使用的-name是而不是-path.如果您给它一个起始位置,.那么.git顶层目录将被调用./.git以用于-path.

所以

find . -path .git -prune -type f

没有给出任何内容,因为-path .git所有文件启动时没有任何匹配项./

find . -not -path .git -type f

为您提供每个文件,因为所有内容都匹配,-not -path .git因此唯一的过滤是-type f将输出限制为文件。

相关内容