When find
is invoked to find nothing, it still exits with code 0. Is there a way to make it return an exit code indicating failure when no file was found?

- 1,448
3 Answers
If your grep
supports reading NUL-delimited lines (like GNU grep
with -z
), you can use it to test if anything was output by find
:
find /some/path -print0 | grep -qz .
To pipe the data to another command, you can remove the -q
option, letting grep
pass on the data unaltered while still reporting an error if nothing came through:
find /some/path -print0 | grep -z . | ...
Specifically, ${PIPESTATUS[1]}
in bash should hold the exit status of grep
.
If your find
doesn't support -print0
, the use grep without -z
and hope that newlines in filenames don't cause problems:
find ... | grep '^' | ...
In this case, using ^
instead of .
might be safer. If output has consecutive newlines, ^
will pass them by, but .
won't.

- 72,889
-
-
@jww unlikely, since with pure POSIX, I don't think you can detect a failure in the middle of a shell pipe. If you have a shell which can do that (via
PIPE_STATUS
or something similar), then it probably has aread
which can do null-delimited input; then you can read a single line, fail if empty; or print it back out andcat
the rest. (Assuming you want to pass on the data to something else, otherwise you can probably dofind ... -exec echo foo {} \+ | grep -q foo
.) – muru Oct 22 '17 at 14:17 -
Is
-z
just to make sure strange characters like\r
are preserved? If piping through grep isn't desired, or there are no weird filenames, then isgrep -z
needed? – mwfearnley Sep 29 '22 at 12:38
You ask specifically for a return code... which I don't see in options. But this is how I solved it (because grep -z
is not on Mac port):
Gives code 0 if 1 line was found
test 1 == `find */.kitchen/ -name private_key | wc -l`
So...
if [ 0 == `find */.kitchen/ -name my-file.txt | wc -l` ] ; then
echo "Nothing found"; exit;
fi
Also, as a generic solution, this might be useful:
Check if pipe is empty and run a command on the data if it isn't

- 889
I am very late to this question, but I just found an elegant answer :-)
find . -type d -empty -and -not -name . -print -exec rmdir {} + | \
awk '{print} END {if (NR == 0) {exit(1)}}'
find
here looks for empty directories in the current directory,
removes the empty directories,
prints the name of removed directories to the pipe,
awk
prints the output of find
and if no output is found NR == 0
, bails out with an error code.
This means I can now iteratively remove empty directories:
while find . -type d -empty -and -not -name . -print -exec rmdir {} + | \
awk '{print} END {if (NR == 0) {exit(1)}}'; \
do echo; done
Replace "my" find
parameters with yours, keep the awk
part either as is or without the {print}
if you do not want to see the output of find
in the terminal, and "voilà".

- 2,495
find
directly supports it. You can do something likefind ... -print0 | grep -qz .
, perhaps, if yourgrep
supports it. – muru Apr 23 '15 at 22:50-exec
. – XZS Apr 23 '15 at 22:56-q
, thengrep
will simply pass through the data, while still breaking the pipeline and reporting a failure if nothing comes through. – muru Apr 23 '15 at 23:02