11

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?

  • Try using foo-exclude-me instead of ./foo-exclude-me. Also try appending -print at the end of the command. – n0pe Mar 7 '13 at 17:55
  • @MaxMackie perfect :) – Tyilo Mar 7 '13 at 18:00
  • It fixed it? Which was the fix that worked for you? I can put it in an answer instead of a comment. – n0pe Mar 7 '13 at 18:01
  • @MaxMackie using both -print and foo-exclude-me instead of ./foo-exclude-me. – Tyilo Mar 7 '13 at 18:04
  • Awesome, looks like Gilles beat me to it though :) – n0pe Mar 7 '13 at 18:13
10
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.

-2

-bash-4.1$ find . -exec ls -l {} + -name 'a.out' -prune -o -name '*' -exec rm -f {} + -exec ls -l {} +

-rw-r--r--. 1 oradba dba  499 Jan 18 19:30 ./a.out
-rw-r--r--. 1 oradba dba  499 Jan 18 20:59 ./b.out
-rw-r--r--. 1 oradba dba  499 Jan 18 20:59 ./c.out
-rw-r--r--. 1 oradba dba  499 Jan 18 20:59 ./d.out

.:
total 16
-rw-r--r--. 1 oradba dba 499 Jan 18 19:30 a.out
-rw-r--r--. 1 oradba dba 499 Jan 18 20:59 b.out
-rw-r--r--. 1 oradba dba 499 Jan 18 20:59 c.out
-rw-r--r--. 1 oradba dba 499 Jan 18 20:59 d.out
rm: cannot remove `.': Is a directory
ls: cannot access ./b.out: No such file or directory
ls: cannot access ./d.out: No such file or directory
ls: cannot access ./c.out: No such file or directory
.:
total 4
-rw-r--r--. 1 oradba dba 499 Jan 18 19:30 a.out

  • Used the prune option to skip a.out and works fine - art.s – user211226 Jan 19 '17 at 1:07
  • You absolutely do not explain why -prune is relevant. -prune is one of the most convoluted options to find 'cause it disables -print (which is enabled by default) – grochmal Jan 19 '17 at 1:54
  • -prune True; if the file is a directory, do not descend into it. - So it will not work itself into the directories as a protection. - art.s – user211226 Jan 19 '17 at 2:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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