Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am trying to use find/grep to find some text patterns in my code base. I want to exclude non-source directories into which my build process duplicates source files:

find . -name *.java -not -name *target* -exec grep -l 'someText' {} \; 2>/dev/null

Unfortunately, I still get target directories in the result, e.g.:


What am I doing wrong and how do I fix it?

share|improve this question
You've got to quote your patterns. SourceFile.java doesn't contain target AFAICT. – Stéphane Chazelas Feb 6 '14 at 22:29
doesn't work with quotes either – amphibient Feb 6 '14 at 22:30
*.java should be "*.java" without quotes -name interprets your argument as literal expression – Kiwy Feb 6 '14 at 22:32
didn't change anything when i tried – amphibient Feb 6 '14 at 22:33
It would if you had any .java files in your current directory. – terdon Feb 6 '14 at 22:37
up vote 6 down vote accepted

-name pattern matches on the file name. SourceFile.java doesn't match *pattern*, so it is included. If you want not to descend into directories whose name contains target, then you'd need:

find . -name '*target*' -prune -o -name '*.java' \
  -exec grep -sl 'someText' {} +

(remember to quote patterns, otherwise they can be expanded by the shell).

For several patterns:

find . \( -name 'pattern1' -o -name 'pattern2' \) -prune 
  -o -name '*.java' -exec grep -sl 'someText' {} +

(AND (-a) is implied when not specified between two predicates. AND has precedence over OR (-o), hence the brackets above).

Note that ! is the portable/standard equivalent of -not.

If you want to match on the full path, then you need to use -path instead like:

find . -name '*.java' ! -path '*target*' -exec grep -sl someText {} +

But that's not stopping find from descending into *target* directories, which is a bit of a waste since find won't report any file in there.

share|improve this answer
very good. however, in the real life example, I would like to exclude more patterns than just target. when i tried find . -name '*target*' -name '*otherPattern*' -prune ..., it didn't work – amphibient Feb 6 '14 at 22:42

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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