15

Edited: I mistakenly misrepresented my problem. A more accurate example now appears below.

I'd like to recursively walk all directories inside a target directory, and stop each recursive call after the first .git directory is found.

For example, if we have these paths:

/home/code/twitter/.git/
/home/code/twitter/some_file
/home/code/twitter/some_other_file 
/home/code/facebook/.git/
/home/code/facebook/another_file
/home/code/configs/.git/
/home/code/configs/some_module/.git/
/home/code/configs/another_module/.git/
/home/code/some/unknown/depth/until/this/git/dir/.git/
/home/code/some/unknown/depth/until/this/git/dir/some_file

I want only these lines in the result:

/home/code/twitter
/home/code/facebook
/home/code/configs
/home/code/some/unknown/depth/until/this/git/dir/

The -maxdepth won't help me here because I don't know how deep the first .git dir will be for each subdirectory of my target.

I thought find /home/code -type d -name .git -prune would do it, but it's not working for me. What am I missing?

1
  • It appears that this may not be possible... I'll leave this question open in case anyone else discovers this in the future and has an answer. Apr 5, 2014 at 3:47

3 Answers 3

8

Sounds like you want the -maxdepth option.

find /home/code -maxdepth 2 -type d -name .git

1
  • 1
    A good thought, but it won't help me here. I've updated my example to more accurately reflect my problem, and I'm so sorry for not having it right the first time. Apr 2, 2014 at 2:11
6

It's tricky and -maxdepth and recursion trickery won't help here, but here's what I would do:

find /home/code -type d -name ".git" | grep -v '\.git/'

In english: find me all directories named ".git" and filter out any occurences in the resultlist which contain ".git/" (dot git slash).

Above commandline will work on all unix systems, however, if you can assert that your find will be "GNU find", then this will also work:

find /home/code -type d -name ".git" ! -path "*/.git/*"

Have fun.

2
  • This would totally work for the problem as it was originally asked by me. Alas, I totally didn't ask the right question for my situation. I've updated my example to more accurately reflect my problem, and I'm so sorry for not having it right the first time. Can you take a look again and share some experience? Apr 2, 2014 at 2:11
  • In this case the answer is provided by UnlimitedInfinity above...
    – Paxsali
    Apr 2, 2014 at 11:56
2

Find all directories which contain a .git subdirectory:

find /home/code -type d -name .git -exec dirname {} \;
4
  • 1
    Hmm. This seems to give me back all dirs with a .git subdir. But I want it to stop at the first dir with a .git subdir for each branch of recursion. Apr 3, 2014 at 1:36
  • @GabeHollombe you are assuming that this directory /home/code/twitter/.git/ will be found by find before these directories get found: /home/code/twitter/some_file /home/code/twitter/some_other_file. Why do you make that assumption? Apr 3, 2014 at 6:47
  • Yep. That's a fair point. I suppose it's more of a request, not an assumption, though. I know I can achieve what I want with some simple scripting, too. I just wondered if there was a simple-ish way to do it with one command. Apr 3, 2014 at 14:38
  • 1
    @GabeHollombe Actually it seems that find processes dot-dirs before non-dot-dirs; however, a directory could have several .dirs and in that case, the output would still be arbitrary. Yes, it looks like you will have to control recursion yourself in a script. I was thinking, maybe the output is more important to you than blocking the recursion, so I took a stab at the problem... Apr 3, 2014 at 15:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .