140

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?

1
  • 2
    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. Commented Jul 25, 2022 at 18:56

8 Answers 8

115
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.

5
  • 15
    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. Commented Oct 30, 2015 at 13:03
  • 7
    i learned to use find ... | read Commented Sep 6, 2019 at 19:53
  • read returns the appropriate exit code, but note that it swallows the result if any Commented Jun 19, 2020 at 21:01
  • grep -F '' does not use regular expressions at all and results in the same output as grep .. Commented Oct 8, 2022 at 16:14
  • 2
    find ... | read is perfect for my use case, I wanted it to swallow the output. Anyone who wants the exit code for branching probably doesn't need the output Commented Mar 19, 2024 at 13:38
44

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 
12
  • 8
    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 -execs it ran. Commented Dec 14, 2017 at 14:51
  • 7
    Works like a clock. A big advantage of this solution is that it doesn't use pipes of subshells - nice for some scripting needs. Commented Sep 18, 2019 at 9:38
  • 4
    This should be suffixed with -quit to immediately exit after a file is found. Commented Jan 2, 2021 at 23:36
  • 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." Commented Jul 13, 2021 at 21:56
  • 2
    @Zombo Just put a ! in front of the find command... Commented Jun 2, 2023 at 13:44
29

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

find /tmp -name something | grep -q "." 
5
  • 6
    Double-quotes serve no purpose here. Commented Apr 10, 2019 at 15:16
  • 7
    While the double quotes serve no code function, they do make it clearer to a reader that the period character is a regex and not a directory. Commented Oct 6, 2019 at 16:30
  • 2
    And if you want the opposite (exit non-zero when the file is found), you can add a negation operator in front ! find /tmp -name badfile | grep -q . Commented Feb 13, 2020 at 21:23
  • And if you want the script to halt on badfile, use … || exit 1 or parens with -e, stackoverflow.com/q/39581150/450917 Commented Nov 1, 2021 at 18:15
  • grep -q will cause find to likely exit with SIGPIPE, which will be a problem if you use -o pipefail. Commented Feb 1, 2022 at 19:08
18

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.

3
  • A few solutions (didn't try them all) here didn't work on a Mac; this did. Commented Feb 8, 2019 at 7:24
  • 1
    Just to note, this can also be written as [[ -n "$(...)" ]] if people find that more readable than using test. Commented Feb 22, 2020 at 3: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). Commented Aug 27, 2021 at 17:38
8

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 
2
  • 1
    It's certainly possible, although not as robust as one might want. Commented Feb 19, 2018 at 7: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. Commented Apr 20, 2019 at 2:12
3

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

test `find /tmp/ -name something -print -quit 2>/dev/null` 
8
  • 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. Commented Feb 6, 2013 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. Commented Feb 7, 2013 at 18:10
  • I'm not sure what your example might be, but I accidentally omitted -print -quit, which might address your concern. Commented Feb 7, 2013 at 18:19
  • 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. Commented Feb 7, 2013 at 22:31
  • 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. Commented Aug 7, 2019 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.

-6

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.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.