100

Even when /tmp has no file called something, searching for it with find will return 0:

  $ find /tmp -name something 
  $ echo $?
  0

How can I get a non-zero exit status when find does not find anything?

yael
  • 1,199
  • 4
  • 13
  • 13
  • If your goal is to pass the list of filenames to a command that behaves poorly when given no arguments, a handy trick is to just add `/dev/null` as an extra argument. It is guaranteed to be empty, so if your goal is to run `wc` this is particularly helpful. Not an answer for every use case. – Tom Boutell Jul 25 '22 at 18:56

8 Answers8

88
find /tmp -name something | grep .

The return status will be 0 when something is found, and non-zero otherwise.

EDIT: Changed from egrep '.*' to the much simpler grep ., since the result is the same.

xeruf
  • 105
  • 4
Steven Monday
  • 13,019
  • 4
  • 35
  • 45
  • 14
    The trailing `*` on the `egrep` regex is completely redundant. Since you are not using `egrep` regular expression syntax, plain old `grep` might be a few microseconds faster. – tripleee Oct 30 '15 at 13:03
  • 2
    i learned to use `find ... | read` – Sam Sep 06 '19 at 19:53
  • read returns the appropriate exit code, but note that it swallows the result if any – xeruf Jun 19 '20 at 21:01
31

Exit 0 is easy with find, exit >0 is harder because that usually only happens with an error. However we can make it happen:

if find -type f -exec false {} +
then
  echo 'nothing found'
else
  echo 'something found'
fi
Zombo
  • 1
  • 1
  • 16
  • 18
  • 7
    As far as I can tell, this doesn't work. The exit code of `find` doesn't seem to depend on the exit codes of any `-exec`s it ran. – Chris Dec 14 '17 at 14:51
  • 2
    Works like a clock. A big advantage of this solution is that it doesn't use pipes of subshells - nice for some scripting needs. – Tim Sep 18 '19 at 09:38
  • No, this will not work as the question was posed. This solution will return 1 if the file is found. It will return 0 if the file is found. This is the opposite of what the OP asked. However, this solution does work as a concept; it just doesn't answer the question. – shrewmouse May 26 '20 at 20:40
  • 1
    @shrewmouse I dont think you understand what the snippet is doing. Notice carefully the `if ... else` is inverted to handle your concern – Zombo May 26 '20 at 22:37
  • 2
    This should be suffixed with `-quit` to immediately exit after a file is found. – Michaël Cadilhac Jan 02 '21 at 23:36
  • @MichaëlCadilhac I found that for dome reason this doesn't works anymore adding `-quit` option to find :s – brunetton Apr 29 '21 at 09:13
  • 5
    To answer whether `find` depends on the exit code of `-exec`, the following blurb from the manual is useful: "If any invocation with the `+` form returns a non-zero value as exit status, then find returns a non-zero exit status." – tianon Jul 13 '21 at 21:56
23

Simplest solution that doesn't print, but exits 0 when results found

find /tmp -name something | grep -q "."
Matt Kneiser
  • 379
  • 2
  • 4
12

Having just found this question whilst trying to find my way to solve a problem with Puppet (change permissions on folders under a directory but not on the directory itself), this seems to work:

test -n "$(find /tmp -name something)"

My specific use case is this:

test -n "$(find /home -mindepth 1 -maxdepth 1 -perm -711)"

Which will exit code 1 if the find command finds no files with the required permissions.

dimo414
  • 376
  • 1
  • 3
  • 16
shearn89
  • 3,143
  • 2
  • 14
  • 39
  • A few solutions (didn't try them all) here didn't work on a Mac; this did. – Alex Hall Feb 08 '19 at 07:24
  • Just to note, this can also be written as `[[ -n "$(...)" ]]` if people find that more readable than using `test`. – dimo414 Feb 22 '20 at 03:19
  • I like this solution because it avoids the pipe and bumping of the PID counter. `[ "$(find ...)" ] && echo Found || echo Not found` with single bracket and no `-n` also works and is portable (POSIX). – amdn Aug 27 '21 at 17:38
7

It's not possible. Find returns 0 if it exits successfully, even if it didn't find a file (which is a correct result not indicating an error when the file indeed doesn't exist).

To quote the find manpage

EXIT STATUS

find exits with status 0 if all files are processed successfully, greater than 0 if errors occur. This is deliberately a very broad description, but if the return value is non-zero, you should not rely on the correctness of the results of find.

Depending on what you want to achieve you could try to let find -print the filename and test against it's output:

#!/bin/bash
MYVAR=`find . -name "something" -print`
if [ -z "$MYVAR" ]; then
    echo "Notfound"
else
   echo $MYVAR
fi
Sven
  • 97,248
  • 13
  • 177
  • 225
  • 1
    It's certainly [possible](https://serverfault.com/a/829314/180589), although not as robust as one might want. – Ruslan Feb 19 '18 at 07:27
  • The manual page is poorly organized; what Ruslan said is documentated under the `exec`/`execdir` option (used with `+`): `If any invocation returns a non-zero value as exit status, then find returns a non-zero exit status.` – Tgr Apr 20 '19 at 02:12
2

I feel that this is the most concise and direct method:

test `find /tmp/ -name something -print -quit 2>/dev/null`
danorton
  • 695
  • 1
  • 8
  • 25
  • 2
    In this case, if find had an error it would print the result to /dev/null, return a non-zero exit, and then have that fixed to 0 by the test command. – Jeff Ferland Feb 06 '13 at 19:24
  • I don't believe that's true. Please describe your example. If there is an error and find exits, then the string will be empty and test will return non-zero. – danorton Feb 07 '13 at 18:10
  • I'm not sure what your example might be, but I accidentally omitted `-print -quit`, which might address your concern. – danorton Feb 07 '13 at 18:19
  • Perhaps the other person who downvoted (presumably for the same reason) can provide a contrary example? – danorton Feb 07 '13 at 22:04
  • The basic problem comes from redirecting stderr to /dev/null. If you're running this as a scripted job, you'd never be aware of any errors even if the script did find a file. You wouldn't be aware that it was perhaps missing files it couldn't access due to permissions issues such as directories that don't have read permissions set. Remove that and let the parent script discard stderr if it is appropriate. – Jeff Ferland Feb 07 '13 at 22:15
  • 1
    Okay, you just don't like my style. For my use cases, any errors that find might report are either noise or so serious that they'll show up elsewhere. In any case, this method correctly answers the ultimate question: "Is there an accessible file in the path by the given name." An error will return a correct answer of "No". If I want to find out why not, I can add more complex code that answers questions not originally posed here. – danorton Feb 07 '13 at 22:31
  • Should it not be `test -n`? i.e. if the output of `find` is not empty, return 0 else return 1...? – jimbobmcgee Jan 22 '19 at 02:07
  • 1
    One small problem is where the path beneath /tmp has a space in it; then `test` fails because it's a unary operator. This can easily be fixed, though, by surrounding the backtick expression with double quotes. – IpsRich Aug 07 '19 at 12:21
0

Here's a little script I called test.py. It improves upon other methods posted in that it will return an error code if one is set, and it additionally set one if find didn't list any files:

from subprocess import Popen
import sys

p = Popen(['find'] + sys.argv)
out, err = p.communicate()
if p.returncode:
    sys.exit(p.returncode)
if not out:
    sys.exit(1)

Here's the command-line output:

$ python test.py . -maxdepth 1 -name notthere
$ echo $?
1
$ find . -maxdepth 1 -name notthere
$ echo $?
0
$ find . -failedarg
find: unknown predicate `-failedarg'
$ echo $?
1

Then, for a result where find had errors but found files:

$ ls -lh
$ d---------  2 jeff users   6 Feb  6 11:49 noentry
$ find .
.
./noentry
find: `./noentry': Permission denied
$ echo $?
1
$ find . | egrep '.*'
.
./noentry
find: `./noentry': Permission denied
$ echo $?
0
python ../test.py 
../test.py
$ echo $?
1

Then, if you want the list of files you can make use of -print 0 passed to find and split the out variable on nulls, or you can just add a print statement for it.

Jeff Ferland
  • 20,239
  • 2
  • 61
  • 85
-5

It is not only find that returns the exit status codes as zero when it successful. In unix what ever the command you execute, if its succeeds then it returns the exit status as zero.

pauska
  • 19,532
  • 4
  • 55
  • 75