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.

  • 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
  • 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) Jun 30 '16 at 16:23

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.

  • ... you execute up to 3 grep (of the whole file) per files ? ... See unix.stackexchange.com/a/293060/27616 for a much better solution, with 1 invocation for the whole thing. 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. 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 :) Jun 30 '16 at 16:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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