Ideally, you'd want to crawl directory trees for directories that contain a .git
entry and stop searching further down those (assuming you don't have further git repos inside git repos).
The problem is that with standard find
, doing this kind of check (that a directory contains a .git
entry) involves spawning a process that executes a test
utility using the -exec
predicate, which is going to be less efficient than listing the content of a few directories.
An exception would be if you use the find
builtin of the bosh
shell (a POSIXified fork of the Bourne shell developed by @schily) which has a -call
predicate to evaluate code in the shell without having to spawn a new sh interpreter:
#! /path/to/bosh -
find . -name '.?*' -prune -o \
-type d -call '[ -e "$1/.git" ]' {} \; -prune -print
Or use perl
's File::Find
:
perl -MFile::Find -le '
sub wanted {
if (/^\../) {$File::Find::prune = 1; return}
if (-d && -e "$_/.git") {
print $File::Find::name; $File::Find::prune = 1
}
}; find \&wanted, @ARGV' .
Longer, but faster than zsh
's printf '%s\n' **/.git(:h)
(which descends into all non-hidden directories), or GNU find
's find . -name '.?*' -prune -o -type d -exec test -e '{}/.git' \; -prune -print
which runs one test
command in a new process for each non-hidden directory.
2022 edit. The find
applet from recent versions of busybox is able to run its [
or test
applet without having to fork a process and reexecute itself inside, so, even though it's still not as fast as the bosh or perl approaches:
busybox find . -type d -exec [ -e '{}/.git' ] ';' -prune -print
In my test is several orders of magnitude faster than the GNU find
equivalent (on a local sample containing a mix of git / cvs / svn repositories with over 100000 directories in total, I get 0.25s for bosh, 0.3s for perl 0.7s for busybox find
, 36s for GNU find
, 2s for GNU find . -name .git -printf '%h\n'
(giving a different result as it also finds .git
files in subdirs of git repositories)).
getpof .git
is what I use. https://github.com/thrig/scripts/blob/master/filesys/getpof.c – thrig Dec 30 '16 at 22:20-maxdepth
if you know a good value. – ctrl-alt-delor Dec 26 '22 at 19:27