43

I am using find -type f command to recursively find all files from a certain starting directory. However, I would like to have some directories prevented from entering and extracting names of files inside. So basically I am looking for something like:

find . -type f ! -name "avoid_this_directory_please"

Is there a functioning alternative to this?

4
  • 10
    There's a dozen questions on the troubles with using -prune: it can be a bit confusing. Also this on stackoverflow describes why it's such an annoying thing to use.
    – ilkkachu
    Mar 8 '17 at 21:26
  • 2
    Even if this is a dupe the best answer here is clearer than the best answer on the "correct" question.
    – chicks
    Oct 9 '18 at 16:04
  • 2
    Hmm, "find -prune isn't working for me" sure sounds different from "how do I exclude directories from find output?" to me ...
    – SamB
    Oct 9 '19 at 19:34
  • @SamB Agreed, this can't possibly be a duplicate. Oct 9 '19 at 22:41
51

This is what the -prune option is for:

find . -type d -name 'avoid_this_directory_please' -prune -o -type f -print

This basically says "if there's a directory called avoid_this_directory_please, don't enter it, otherwise, if it's a regular file, print its pathname".

You may also prune the directory given any other criteria, e.g. its full pathnames from the top-level search path:

find . -type d -path './some/dir/avoid_this_directory_please' -prune -o -type f -print
5
  • 2
    i was going to write the same thing, slightly differently, as find . \( -type d -name 'avoid_this_directory_please' -prune \) -o \( -type f -print \), but I like your syntax better. Thanks. Mar 8 '17 at 21:20
  • 3
    @TimKennedy You would probably need the parens if you wanted to do find . -type d \( -name "A" -o -name "B" \) -prune -o -type f -print.
    – Kusalananda
    Mar 8 '17 at 21:22
  • good point. i don't even know when/where I learned to do it with the parentheses. that age is lost in the mists of time. :) Mar 8 '17 at 21:23
  • 2
    This will of course prune off any directories called avoid_this_directory_please anywhere in the tree, not just top level ones. -path would allow for more control in that, as the man page (quoted below by Xen2050) states.
    – ilkkachu
    Mar 8 '17 at 21:30
  • I did not know that -prune considered everything after the first find argument, including -type and was puzzled at failing to prune directories with find / -type f -path /proc -prune -o -name foo -print. Seeing both -type d and -type f in the same command is what made it click for me. Now I finally feel confident in using find, thanks.
    – kelvin
    Apr 27 '20 at 2:18
14

To avoid a directory try the -path test:

find . -type f ! -path '*/avoid_this_directory_please/*'
3
  • 8
    Note that while it will prevent files inside avoid_this_directory_please from being selected (unless their path contain invalid characters), it will not stop find from descending in there. That's why -prune is better here. Mar 8 '17 at 21:22
  • This is sooooo much better than using prune. I always have to read for half an hour to figure out specifying what I don't want for find and then pair with OR logic to obtain the files I want.
    – Merlin
    Jul 29 '19 at 4:30
  • @Merlin It obviously depends on what you want to achieve. With -prune, find won't even look in the selected paths, while with ! -path, it would still enter the path and examine everything.
    – Kusalananda
    Sep 4 '19 at 11:27
9

From man find, in the -path section, apparently combining the other 2 answers

To  ignore a whole directory tree, use -prune rather than
checking every file in the tree.  For example, to skip the directory
`src/emacs'  and  all  files and directories under it, and print the
names of the other files found, do something like this:

          find . -path ./src/emacs -prune -o -print
7

Try this

find -name "*.js" -not -path "./directory/*"
1
  • This works if only you are looking for one extension type. The following will fail: find -name "*.js" -o -name "*.css" -not -path "./directory/*" Dec 4 '17 at 10:28

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