5

I'm trying to figure out how to use the linux "find" command (or another command that will get the job done) to return a list of file paths/directories that do not contain a directory of a certain name.

~/web/domain1.com/public_html/bar
~/web/domain2.com/public_html/
~/web/domain3.com/public_html/bar
~/web/domain4.com/public_html/

I want all of the paths that don't contain the directory named "bar" (domain2.com and domain4.com). Any idea how I can get find to output such a list?

Thanks!

4 Answers 4

2
find ~ -type d '!' -exec test -d '{}/bar' ';' -print

... but this probably isn't exactly what you want; for the example directories you gave, it'll output:

/path/to/home
/path/to/home/web
/path/to/home/web/domain1.com
/path/to/home/web/domain1.com/public_html/bar
/path/to/home/web/domain2.com
/path/to/home/web/domain2.com/public_html
/path/to/home/web/domain3.com
/path/to/home/web/domain3.com/public_html/bar
/path/to/home/web/domain4.com
/path/to/home/web/domain4.com/public_html

i.e. it lists every directory that doesn't contain a "bar" subdirectory, including even the "bar" directories themselves (unless they contain their own bar subdirectories...). You probably want to add an additional restriction, like only listing directories at a certain depth:

find ~ -type d -depth 3 '!' -exec test -d '{}/bar' ';' -print

or with a certain name:

find ~ -type d -name public_html '!' -exec test -d '{}/bar' ';' -print

...both of which print:

/path/to/home/web/domain2.com/public_html
/path/to/home/web/domain4.com/public_html
2

I don't know about using find, but this works:

justin@media:/tmp/sf$ for x in *;do [ -e $x/public_html/bar ] || echo $x;done
domain2.com
domain4.com
1

Why not use grep?

edited:

find . -type d | grep -v "bar"

This will list all directories, grep will read from standard input and then do an inverse match on the string "bar"

3
  • Isn't grep for searching inside of files? What would I put it front of the pipe?
    – erikcw
    Mar 12, 2010 at 23:54
  • 1
    @Keiran: find . -type d | grep -v "/bar$" Now the problem is that bar may be a file instead of a directory. Mar 13, 2010 at 1:14
  • 1
    @erikcw: no, this is the beauty of Unix tools: they work on standard input or files if filenames are given on the command line. That allows them to be chained (piped) together. Mar 13, 2010 at 1:16
1

If you want to match those exact directories only and not any instance of bar/ then a command like this would work.

find . \! -wholename '*/web/domain1.com/public_html/bar/*' \
       \! -wholename '*/web/domain1.com/public_html/bar/'  \
       \! -wholename '*/web/domain3.com/public_html/bar/*' \
       \! -wholename '*/web/domain3.com/public_html/bar/'

If you want to ignore bar/ directory where every it is found then you would probably want something like this.

find . \! -wholename '*/bar/*' \! -wholename '*/bar/'

You must log in to answer this question.

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