1

I'd like to use find to report files under the following conditions:

  1. If the file contains the word "Serializable"
  2. Then report the file if it does NOT contain the word "serialVersionUID"

Something like:

find . -name "*.java" -exec grep "Serializable" {} \; <magic stuff here> grep "serialVersionUID" {} \; -print

So am I smoking crack and would be better served by awk?

Thanks for your help.

D-Klotz
  • 123
  • 6
  • Thank you. I gave it a try but perhaps there is a version problem? – D-Klotz Oct 23 '14 at 20:03
  • @MarkPlotnick You could post that as an answer. Note that the -a is optional. – jw013 Oct 23 '14 at 20:36
  • I agree. FYI. This is what I ended up using: find . -name "*.java" -exec grep -E -q '(implements [a-zA-Z0-9]*[ ]*|[,]+[ ]+)Serializable' {} \; -a ! -exec grep -q "serialVersionUID" {} \; -a -print – D-Klotz Oct 23 '14 at 21:15
  • http://unix.stackexchange.com/a/293060/27616 shows that indeed you are better served by awk ^^ (Only 1 invocation of awk for the whole search, instead of multiple invocation of grep per files) – Olivier Dulac Jun 30 '16 at 16:23

1 Answers1

2

The -exec operand of find evaluates to true if the command succeeds (i.e. returns zero) and false if it fails (returns nonzero), so you can use the success/failure of grep as part of the expression used by find.

Together with find's ! operand, which negates the following operand, you can search for files for which one grep command succeeds and another grep command fails:

find . -name "*.java" \
    -exec grep -q "Serializable" {} ";" -a \
    ! -exec grep -q "serialVersionUID" {} ";" -a -print

The -q option tells grep not to print out anything; we're only interested in its return value.

The -a operand isn't strictly required, but it doesn't slow things down and I like to use it when there's a possibility that the expression may grow even more complex and require -o or parentheses.

Mark Plotnick
  • 25,413
  • 3
  • 64
  • 82
  • ... you execute up to 3 grep (of the whole file) per files ? ... See http://unix.stackexchange.com/a/293060/27616 for a much better solution, with 1 invocation for the whole thing. – Olivier Dulac Jun 30 '16 at 16:17
  • 1
    @OlivierDulac Up to two greps, each of which only reads up until the first match. The -q option makes grep exit right after the first match. But you're quite right - there are other utilities that can do this with just one pass through the file. I just suggested the minimal changes necessary to make the OP's find/grep command work. – Mark Plotnick Jun 30 '16 at 16:51
  • @MarkPlotnick : sorry for the tone of my first comment ... And indeed, 2 not 3. I understand that you stayed close to the OP's attempt, but it usually is akin to a XYProblem : we should solve the need, not fix the how :) – Olivier Dulac Jun 30 '16 at 16:54