Pipe find into grep -v

There is no need in xargs here. Also you need to use grep with -L option (files without match), cause otherwise it will output the file content instead of its name, like in your example.

find . -type f -iname "*.java" -exec grep -L "something somethin" {} \+

You've almost got it really...

find . -type f -iname "*.java" -print0 | xargs -0 grep -v "something something"

The dot '.' says to start from here. (yours implies it.. but never assume).

-iname uses case-insensitive search, just in case (or just in no-case).
-print0 sends filenames to xargs with a trailing \x00 character, which prevents problems with filenames having spaces in them.

the '-0' on xargs says to expect filenames ending with \x00 instead of returns.

and your grep command...

Pretty much got it.


EDIT::

From your update:

find . -type f -iname "*pb.java" -print0 | xargs -0 grep -iL "something"

should help. (Added -L from @rush's answer, good job)

I get the idea that your grep needs either the '-i' option, or to be less explicit.

Try the command in parts... does THIS output filenames that seem proper?

find . -type f -iname "*pb.java"

If so, then your problem is likely either your grep search pattern is not matching (spelling error? it happens!), or there just aren't any matches.

Absolute worst case:

grep -riL "something" *

will do a LOT more work searching everything, but should give you some output.


The computer is being a computer: it's doing what you told it to do instead of what you wanted it to do.

grep -v "something something" prints all lines that do not contain something something. For example, it prints two lines among the following three:

hello world
this is something something
something else

To print files that do not contain extends SomethingSomething anywhere, use the -L option:

grep -L -E 'extends[[:space:]]+SomethingSomething' FILENAME…

Some versions of grep do not have the -L option (it is not specified by POSIX). If yours doesn't, have it print nothing, and use the return code to have the calling shell do whatever it should do instead.

grep -q -E 'extends[[:space:]]+SomethingSomething' FILENAME ||
echo "$FILENAME"

Alternatively, use awk.

awk '
    FNR == 1 && NR != 1 && !found { print fn }
    FNR == 1 { fn = FILENAME; found = 0; }
    /extends[[:space:]]+SomethingSomething/ { found = 1 }
    END { if (fn != "" && !found) print fn }
'

On Linux or Cygwin (or other system with GNU grep), you don't need to use find, as grep is capable of recursing.

grep -R --include='*.java' -L -E 'extends[[:space:]]+SomethingSomething'

If your shell is ksh or bash or zsh, you can make the shell do the filename matching. On bash, run set -o globstar first (you can put this in your ~/.bashrc).

grep -L -E 'extends[[:space:]]+SomethingSomething' **/*.java

Tags:

Grep

Pipe

Find