How to exclude a directory in find . command
Use the -prune
switch. For example, if you want to exclude the misc
directory just add a -path ./misc -prune -o
to your find command:
find . -path ./misc -prune -false -o -name '*.txt'
Here is an example with multiple directories:
find . -type d \( -path dir1 -o -path dir2 -o -path dir3 \) -prune -false -o -name '*.txt'
Here we exclude ./dir1, ./dir2 and ./dir3 in the current directory, since in find
expressions it is an action that acts on the criteria -path dir1 -o -path dir2 -o -path dir3
(if dir1 or dir2 or dir3), ANDed with type -d
.
To exclude directory name at any level, use -name
:
find . -type d \( -name node_modules -o -name dir2 -o -path name \) -prune -false -o -name '*.json'
I find the following easier to reason about than other proposed solutions:
find build -not \( -path build/external -prune \) -name \*.js# you can also exclude multiple pathsfind build -not \( -path build/external -prune \) -not \( -path build/blog -prune \) -name \*.js
Important Note: the paths you type after -path
must exactly match what find
would print without the exclusion. If this sentence confuses you just make sure to use full paths through out the whole command like this: find /full/path/ -not \( -path /full/path/exclude/this -prune \) ...
. See note [1] if you'd like a better understanding.
Inside \(
and \)
is an expression that will match exactly build/external
(see important note above), and will, on success, avoid traversing anything below. This is then grouped as a single expression with the escaped parenthesis, and prefixed with -not
which will make find
skip anything that was matched by that expression.
One might ask if adding -not
will not make all other files hidden by -prune
reappear, and the answer is no. The way -prune
works is that anything that, once it is reached, the files below that directory are permanently ignored.
This comes from an actual use case, where I needed to call yui-compressor on some files generated by wintersmith, but leave out other files that need to be sent as-is.
Note [1]: If you want to exclude /tmp/foo/bar
and you run find like this "find /tmp \(...
" then you must specify -path /tmp/foo/bar
. If on the other hand you run find like this cd /tmp; find . \(...
then you must specify -path ./foo/bar
.