我想找到位于某个目录中的所有 git 存储库,但不是它的子目录,例如~/repo
。
find ~/repo -depth 2 -type d -name '.git' | while read repo …
或
for repo in ~/repo/*/.git …
使用查找的版本比具有globbing模式的版本慢。我对此感到非常惊讶,因为没有理由说明为什么一个方法需要比另一个方法更多的系统调用来收集它的信息。我尝试了一个更聪明的 find 调用
版本find ~/repo -depth 3 -prune -o -depth 2 -type d -name '.git' -print | while read repo …
没有任何明显的改善。很遗憾,我无法trace system calls弄明白发现的工作方式。
这两种方法之间巨大速度差异的解释是什么? (shell是/bin/sh
,我认为它是 bash 的一些过时版本。)
答案 0 :(得分:2)
您可以使用:
find ~/repo -maxdepth 2 -mindepth 2 -type d -name '.git'
这将更准确地再现globbing的逻辑。另请注意,该选项不可移植,不适用于GNU系统。
顺便说一句,我会使用-exec
的{{1}}选项而不是流入while循环。
答案 1 :(得分:1)
更新:documentation of GNU find
中未指定带参数(-depth
)的测试-depth 2
。它可能是OSX扩展。不要用它!
使用-mindepth 2 -maxdepth 2
代替{@ 3}}中的@ hek2mgl建议。
当使用find
时,-depth 2
的OSX版本似乎不必要地下降到深度超过2级的目录中(但这是正确的行为,见下文)。< / p>
你可以告诉它不要在-prune
之后立即添加-depth 2
(如果你把它放在其他地方似乎没有任何影响):
find ~/repo -depth 2 -prune -type d -name .git
一些基准:
$ time (find . -depth 4 -prune -type d -name .git | wc -l)
20
real 0m0.064s
user 0m0.009s
sys 0m0.046s
最后移动了-prune
,它突然需要很长时间才能运行:
$ time (find . -depth 4 -type d -name .git -prune | wc -l)
20
real 0m12.726s
user 0m0.325s
sys 0m9.298s
第二个想法(在仔细阅读man find
之后)-depth 2
不需要find
在两个级别以下的目录中停止下降。它可能是需要-depth 2
或其他内容(f.e. find . -depth 2 -or -name .git
)的更复杂条件的一部分。
要强制它停止下降超过两个级别,您必须使用-maxdepth 2
或-depth 2 -prune
。
-maxdepth
告诉它不要超过两个级别; -depth 2 -prune
告诉它如果被检查的目录深两层,就不要再进入子目录。他们有相同的行为,选择一个或另一个是一个偏好的问题。我会选择-maxdepth 2
,因为它更清楚。
因为-depth 2
不可移植,所以最终命令应该是:
find ~/repo -mindepth 2 -maxdepth 2 -type d -name '.git' -print
感谢@ hek2mgl提及兼容性问题。