I want to list only the directories that are not inside a .git/ directory on my current path.

I'm trying this:

find . -path "**/.git" -prune -o -print -type d

The .git dirs are excluded, but the snippet is also listing files. But it should not as I specified -type d. How to make the find utility behave as I described?


You've used -print before -type d, so find print all things not satisfied the first expression.

You want to swap them:

find . -path '*/.git' -prune -o -type d -print

or using predicate only, so you can omit -print:

find . ! \( -path '*/.git' -o -path '*/.git/*' \) -type d

Also note that you only need to use one asterisk */.git, double asterisk ** has no special meaning to find pattern matching. And you can make it simpler, more portable and slightly faster by using -name instead of -path:

find . -name .git -prune -o -type d -print
  • thank you. The first solution worked. However, if I ommit -print, as you suggested, I get .git directories, which I don't want. If i put back the magical -print, than it all works as I want. Why that happens? That's really unexpected. – ninrod Feb 25 '16 at 4:54
  • think I've found the answer here. Without -print the default action applies to all branches, even pruned ones. – ninrod Feb 25 '16 at 4:59
  • Yes, my bad. I am not near my laptop to check. Here omit -print make it to be applied for the whole expression. – cuonglm Feb 25 '16 at 5:22
  • Thanks, now both solutions work fine. With prune I only have to specify */.git while find needs us to say both */.git and */.git/* when using predicate only. Why is that? – ninrod Feb 25 '16 at 12:35
  • Because */.git can not match something like foo/.git/bar. – cuonglm Feb 25 '16 at 12:43

Due to lack of knowledge of the find command, I just use a less efficient but most likely equally useful and probably more readable one-liner that also involves grep:

find . -type d | grep -v "/\.git"
  • It's not equal. It gives wrong result if filename contain newline. – cuonglm Feb 25 '16 at 7:13
  • You'd need grep -Ev '\.git($|/)', otherwise you're ignoring e.g. .gitignore files. And even then that would break on file names containing newlines (this one isn't always a concern in practice). Given that there's a simple find solution, such an alternate method is not called for. – Gilles 'SO- stop being evil' Feb 25 '16 at 21:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.