linux - Using Unix's find command to find directories matching name but not subdirectories with same name

07
2014-07
  • Gabe Hollombe

    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?

  • Answers
  • Digital Chris

    Sounds like you want the -maxdepth option.

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

  • Paxsali

    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.

  • UnlimitedInfinity

    Find all directories which contain a .git subdirectory:

    find /home/code -type d -name .git -exec dirname {} \;
    

  • Related Question

    linux - Unix, find command, and false negative
  • xtian

    Performing a search from the current directory where this file resides, this find command finds the file.

    # find . page.tpl.php
    

    However, when I search from a child directory, this command,

    # find ../. page.tpl.php
    

    prints out the list of files, WITH the requested file listed in the output,

    .././parent_dir/page.tpl.php
    

    However, the results are,

    find: `page.tpl.php': No such file or directory
    

    Then when I add the -name argument it works,

    # find ../. -name page.tpl.php
    

    I simply forget to use arguments sometimes and the false negative is really aggravating. What's going on?


  • Related Answers
  • RedGrittyBrick

    find [path] [expressions]

    A filename isn't an expression.

    The default action is to print.

    For path, ".." is better than "../." you almost never need to include "." unless it's at the start of a relative path.

  • Chris Ting

    The command find uses:
    find [-H] [-L] [-P] [path...] [expression]

    Your first example was:
    find ../. page.tpl.php

    What you did was give find two search paths. As the default expression is print, the contents of the two paths were printed to stdout.

    Consider this:

    mkdir a b c 
    touch  a/file1 a/file2 b/SANTACLAUS c/MONKEYS
    find a b
    
    $ find a b
    a
    a/file2
    a/file1
    b
    b/SANTACLAUS
    

    Your second example was:
    .././parent_dir/page.tpl.php

    Here you provided one search path. The error tells you that page.tpl.php wasn't found in CWD. I assume this was due to your not having the file 'page.tpl.php' under the directory 'parent_dir'.