How to exclude a directory in find . command
If -prune
doesn't work for you, this will:
find -name "*.js" -not -path "./directory/*"
Caveat: requires traversing all of the unwanted directories.
Use the -prune
primary. For example, if you want to exclude ./misc
:
find . -path ./misc -prune -o -name '*.txt' -print
To exclude multiple directories, OR them between parentheses.
find . -type d \( -path ./dir1 -o -path ./dir2 -o -path ./dir3 \) -prune -o -name '*.txt' -print
And, to exclude directories with a specific name at any level, use the -name
primary instead of -path
.
find . -type d -name node_modules -prune -o -name '*.json' -print
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 paths
find 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
.