47

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?

user219860
  • 471
  • 1
  • 4
  • 3

4 Answers4

56

This is what the -prune option is for:

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

You may interpret the above as "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
Kusalananda
  • 333,661
  • 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. – Tim Kennedy Mar 08 '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 08 '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. :) – Tim Kennedy Mar 08 '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 08 '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 02:18
14

To avoid a directory try the -path test:

find . -type f ! -path '*/avoid_this_directory_please/*'
  • 9
    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. – Stéphane Chazelas Mar 08 '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 04: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 04 '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
Xen2050
  • 2,354
7

Try this

find -name "*.js" -not -path "./directory/*"
  • This works if only you are looking for one extension type. The following will fail:

    find -name "*.js" -o -name "*.css" -not -path "./directory/*"

    – Subhamoy S. Dec 04 '17 at 10:28