7

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
    I don't think find directly supports it. You can do something like find ... -print0 | grep -qz ., perhaps, if your grep supports it. – muru Apr 23 '15 at 22:50
  • My grep is gnu grep so it supports this nice idea. Unfortunately, I also need the find output to be piped somewhere and I cannot replace the pipe with -exec. – XZS Apr 23 '15 at 22:56
  • I'm making something. – Gene Apr 23 '15 at 22:57
  • 1
    @XZS you can skip the -q, then grep 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
  • @muru A do-nothing grep guarding the pipe, very elegant. Turn this into an answer and it will be accepted. – XZS Apr 23 '15 at 23:19
7

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.

  • Grep's -z is a GNU extension. Do you have something for more Posixy? – user56041 Oct 21 '17 at 9:11
  • @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 a read which can do null-delimited input; then you can read a single line, fail if empty; or print it back out and cat the rest. (Assuming you want to pass on the data to something else, otherwise you can probably do find ... -exec echo foo {} \+ | grep -q foo.) – muru Oct 22 '17 at 14:17
3

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

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.