It's inefficient (runs a bunch of subprocesses), but the following will do the job with GNU or modern BSD find
:
find . -type d -exec test -d '{}/.git' ';' -prune -o -type d -print
If you're not guaranteed to have a find
with any functionality not guaranteed in the POSIX standard, then you might need to take even more of an efficiency loss (to make {}
its own token, rather than a substring, by having a shell run the test):
find . -type d -exec sh -c 'test -d "$1/.git"' _ '{}' ';' -prune -o -type d -print
This works by using -exec
as a predicate, running a test that find
doesn't have support for built-in.
Note the use of the inefficient -exec [...] {} [...] \;
rather than the more efficient -exec [...] {} +
; as the latter passes multiple filenames to each invocation, it has no way to get back individual per-filename results and so always evaluates as true.