我想仅.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
不打印以下命令中的./.git
and结果:./.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
将输出限制为文件。