Exclude directory in find

find

How can I find every file and directory matching a pattern, excluding one directory using find?

Say I have the following file structure;

.
  foo-exclude-me/
    foo.txt
  foo-exclude-me-not/
    foo.txt
  bar/
    foo.txt
    foobar/
      bar.txt
      foofoo.txt

how would I get the following output using find:

./bar/foo.txt
./bar/foobar
./bar/foobar/foofoo.txt
./foo-exclude-me-not
./foo-exclude-me-not/foo.txt

I have tried using both of the following command:

find . -name 'foo-exclude-me' -prune -o -name 'foo*'
find . -name 'foo*' \! -path './foo-exclude-me/*'

but both of them return this:

./bar/foo.txt
./bar/foobar
./bar/foobar/foofoo.txt
./foo-exclude-me # << this should be excluded
./foo-exclude-me-not
./foo-exclude-me-not/foo.txt

How can I properly exclude the foo-exclude-me directory?

Best Answer

find . -name 'foo-exclude-me' -prune -o -name 'foo*' -print

With no -print, the implicit default action applies to every match, even pruned ones. The explicit -print applies only under the specified conditions, which are -name 'foo*' only in the else branch of -name 'foo-exclude-me'.

Generally speaking, use an explicit -print whenever you're doing something more complex than a conjunction of predicates.

Your second attempt with ! -path './foo-exclude-me/*' didn't work because ./foo-exclude-me doesn't match ./foo-exclude-me/* (no trailing /). Adding ! -path ./foo-exclude-me would work.

Related Question