Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

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!

share|improve this question

4 Answers 4

up vote 1 down vote accepted
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
share|improve this answer

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
share|improve this answer

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/'
share|improve this answer

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"

share|improve this answer
    
Isn't grep for searching inside of files? What would I put it front of the pipe? –  erikcw Mar 12 '10 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. –  reinierpost Mar 13 '10 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. –  reinierpost Mar 13 '10 at 1:16

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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