如何加快查找列出git存储库的速度?

时间:2015-06-25 08:49:16

标签: git shell sh

我想找到位于某个目录中的所有 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 的一些过时版本。)

2 个答案:

答案 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建议。

OSX特定

当使用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提及兼容性问题。