2

what I want to do is to find all files based on some search query and get parents parent directory (../..) full path.

For example find . -name "__openerp__.py" and then for each file execute something along the lines of (cd ../..; pwd). Then pipe everything to uniq.

4 Answers 4

5

Assuming none of the file names contain newline characters:

find "$PWD" -name __openerp__.py  | awk -F/ -vOFS=/ 'NF-=2' | sort -u
3

Putting aside that there would be issues with file names that contain newlines, there are a couple of efficiency improvements I can think of:

  1. Pass the $PWD directly to find, instead of determining it for each sub-shell. This will make find include the full path in its output.
  2. Cut parent directory names off with rev and cut.

So I would suggest the following to get a list of all directories containing the desired file:

find "$PWD" -name '__openerp__.py' |
rev                                | 
cut -d/ -f3-                       |
rev

Note that find does not order its output, so it should be sorted before uniq'ing it. As sort already supports squeezing identical elements (-u switch), the original question can then be answered with:

find "$PWD" -name '__openerp__.py' |
rev                                | 
cut -d/ -f3-                       |
rev                                |
sort -u
1
  • +1 Good point about sort -u. I initially thought that all the duplicate entries would be adjacent, but there isn't any reason for it. Commented Jan 29, 2014 at 13:13
2

If I understand correctly, you want the list of directories containing a subdirectory containing a file called __openerp__.py, without duplicates.

In zsh:

print -rl -- **/__openerp__.py(:h:h) | sort -u

or

a=(**/__openerp__.py(:h:h)); print -rl -- ${(u)a}
1
  • +1 for (:h:h) didn't knew this one in zsh globbing.
    – JackLeo
    Commented Jan 30, 2014 at 11:18
-1
find . -name "__openerp__.py" -exec sh -c '(cd "{}"/../../; pwd)' \; | uniq
3
  • 1
    Never include {} in the sh code. Commented Jan 29, 2014 at 13:06
  • @StephaneChazelas why?
    – JackLeo
    Commented Jan 29, 2014 at 13:12
  • 3
    Because it's interpreted as shell code, so if you have for instance a file called $(rm -f "$HOME"), it will have expensive consequences. Also it doesn't work at all in many find implementations. Use sh -c 'cd -P "$1/../.." && pwd' sh {} \; instead. Commented Jan 29, 2014 at 13:15

You must log in to answer this question.

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