¿Cómo acelerar el hallazgo para listr repositorys git?

Quiero encontrar todos los repositorys de git en algún directory, pero no en sus subdirectorys, digamos ~/repo . Dos enfoques simples son

 find ~/repo -depth 2 -type d -name '.git' | while read repo … 

o

 for repo in ~/repo/*/.git … 

La versión que utiliza find tiene magnitudes más lentas que la que tiene el patrón globbing. Estoy muy sorprendido por esto, porque no hay una razón real por la que un método necesite más llamadas al sistema que el otro para recostackr su información. Intenté una versión más inteligente de la invocación de búsqueda

 find ~/repo -depth 3 -prune -o -depth 2 -type d -name '.git' -print | while read repo … 

sin ninguna mejora notable. Lamentablemente, no pude rastrear las llamadas al sistema para descubrir cómo funciona Find aquí.

¿Qué explica la gran diferencia de velocidad entre estos dos methods? (El shell es /bin/sh que creo que es una versión obsoleta de bash ).

Actualización : la testing -depth con arguments ( -depth 2 ) no está especificada en la documentation de GNU find . Probablemente sea una extensión OSX. ¡No lo uses!

Use -mindepth 2 -maxdepth 2 lugar, como lo sugiere @ hek2mgl en su respuesta .


Específico de OSX

Parece que la versión OSX de find desciende innecesariamente en directorys de más de 2 niveles cuando se utiliza -depth 2 ( pero este es el comportamiento correcto , ver más abajo).

Puede decirle que no haga eso agregando -prune inmediatamente después de -depth 2 (parece que no tiene ningún efecto si lo coloca en otro lugar):

 find ~/repo -depth 2 -prune -type d -name .git 

Algunos puntos de reference:

 $ time (find . -depth 4 -prune -type d -name .git | wc -l) 20 real 0m0.064s user 0m0.009s sys 0m0.046s 

Moved- -prune al final y de repente necesita mucho time para ejecutarse:

 $ time (find . -depth 4 -type d -name .git -prune | wc -l) 20 real 0m12.726s user 0m0.325s sys 0m9.298s 

Observaciones

Pensándolo bien (y después de una lectura más cercana de man find ) -depth 2 no requiere que find para dejar de descender en directorys de más de dos niveles. Puede ser parte de una condición más compleja que requiera -depth 2 o algo más (fe find . -depth 2 -or -name .git ).

Para forzarlo a que deje de descender más de dos niveles, debe usar ya sea -maxdepth 2 o -depth 2 -prune .

  • -maxdepth le dice que no vaya más allá de dos niveles;
  • -depth 2 -prune le dice que deje de descender a los subdirectorys si el directory bajo examen tiene dos niveles de profundidad.

Tienen un comportamiento equivalente, elegir uno u otro es una cuestión de preference. Yo elegiría -maxdepth 2 porque es más claro.

Conclusión

Como -depth 2 no es portable, el command final debería ser como:

 find ~/repo -mindepth 2 -maxdepth 2 -type d -name '.git' -print 

Gracias @ hek2mgl por mencionar el problema de compatibilidad.

Puedes usar:

 find ~/repo -maxdepth 2 -mindepth 2 -type d -name '.git' 

Esto reproduciría la lógica del globbing más exactamente. También tenga en count que la opción no es portátil y no funcionará en los sistemas GNU.

Por cierto, en lugar de conectarme a un bucle while, usaría la opción -exec de find .