O -exec do operando de find é avaliado como verdadeiro se o comando for bem-sucedido (ou seja, retornar zero) e falso se falhar (retorna diferente de zero). pode usar o sucesso / falha de grep como parte da expressão usada por find .
Juntamente com o operando find ! , que nega o seguinte operando, você pode procurar por arquivos para os quais um comando grep é bem-sucedido e outro comando grep falhar:
find . -name "*.java" \
-exec grep -q "Serializable" {} ";" -a \
! -exec grep -q "serialVersionUID" {} ";" -a -print
A opção -q informa grep para não imprimir nada; estamos interessados apenas em seu valor de retorno.
O operando -a não é estritamente necessário, mas não atrasa as coisas e eu gosto de usá-lo quando existe a possibilidade de a expressão ficar ainda mais complexa e exigir -o ou parênteses.