1

I use find to get all txt files , then use grep to find if a special word in the txt files which find by find command.

if find "/home/test/" -name "*.csv" -exec grep "pattern" {} \;; then
    echo "find it in txt files";
else
    echo "not find in txt files";
fi

The program always outputs "find it" although the conditions are not met.

Rosand Liu
  • 409
  • 2
  • 5
  • 14
  • 1
    *-name* must be quoted to prevent shell globbing. to get exit status you could use *\\( -exec grep ... {} \; -a -exec echo ... \; \\)* – alecxs Aug 20 '20 at 12:00
  • 2
    Does this answer your question? [Bash - find exec return value](https://stackoverflow.com/questions/31713189/bash-find-exec-return-value) – P.P Aug 20 '20 at 12:13
  • Do you want to print `find it` if `pattern` is matched in any file or if it's matched in all files? – Ed Morton Aug 21 '20 at 04:26

2 Answers2

2

Unless punctuated by a plus sign, an -exec predicate doesn't affect find's exit status. See:

$ find . -prune -exec test -f {} ';'
$ echo $?
0
$ find . -prune -exec test -f {} '+'
$ echo $?
1

But even with the plus sign, find's exit status is unreliable. It may invoke grep multiple times due to memory limitations, and if any invocation exits with a non-zero value, find's exit status will also be non-zero. In other words, if all invocations of grep find a match but one doesn't, find's exit status will not be zero. This applies to xargs as well.

Here is a way to walk around these constraints:

! find . -name '*.txt' -exec sh -c '! "$@"' _ grep 'pattern' /dev/null {} +
oguz ismail
  • 1
  • 16
  • 47
  • 69
2

find exits normally if all files found are processed. Specifically, this ignores the return code of the command executed.

If you want the exit code of grep, you're better off with xargs, which can send the output of find as command-line arguments to grep. For example:

find ./ -name '*.txt' -print0 | xargs -0r grep "pattern"

This has the advantage that you can still customize find parameters over grep -r.

Of course you can use GNU grep with --exclude and --include for similar features, but find is more powerful for its expressions.

iBug
  • 35,554
  • 7
  • 89
  • 134
  • Thanks, I try to use the command `if find ./ -maxdepth 1 -name '*asdfasd*.txt' -print0 | xargs -0r grep "asdfqwerytavasdf" ; then echo "find it"; else echo "not find"; fi` to test if it right. I find if the `find` command returns an empty file list, the console will show `find it`, But I like it show `not find`. How to deal with this problem? – Rosand Liu Aug 24 '20 at 07:20
  • I debug the `if` command ? So I first input `find ./ -maxdepth 1 -name '*asdfasd*.txt' -print0 | xargs -0r grep "asdfqwerytavasdf"` in console, then input `echo $?`, the console output `0` , I very confused about this result, since the output is `0` , above `if` command need output `not find` – Rosand Liu Aug 24 '20 at 07:27
  • I write a shell program, find the empty variable is true in `if` command... – Rosand Liu Aug 24 '20 at 07:54