2

In general, if we want to execute a command if find identifies files corresponding to certain specs, we can use -exec. But in my case I want to exit the shell/script if find found a match and -exec can't do that. [Apparently find's -exec cannot call bash functions either.)

For instance in a script to remove a tree if and only if it contains only empty directories, I'd like to first check for presence of any non-directory and abort with an error message at the first such unexpected entry.

So far whenever I need to do something like this, I put the output to a variable (possibly using -quit with find) and testing for it being empty or not.

So my script looks like:

#! /bin/sh
INTRUDER="$(find "$@" ! -type d -print -quit)"
if [ -n "$INTRUDER" ] ; then
    echo "Found non-dir $INTRUDER; leaving the arguments untouched"
    exit 1
fi
rm -R "$@"

Is there a different/better approach than this? By "better" I mean, smaller to code, more portable (if there is any portability issue with the above), etc. By "different" I mean by avoiding the extra variable and testing for its length.

2
  • possible duplicate of How to stop the find command after first match?
    – cuonglm
    Sep 19, 2014 at 4:02
  • 3
    Hello and thanks for your attention. I (already noted that I) know about -quit. But it merely stops searching after first match. I am asking for a workaround to not being able to -exec a shell built-in (for this particular example to exit the shell, not exit the find). So this is not a dup. Please remove that tag.
    – jamadagni
    Sep 19, 2014 at 4:12

1 Answer 1

2

This one worked for me:

find "$@" ! -type d -exec kill -9 $$ \; -quit && rm -R "$@"
  • If find exits normally (nothing is found) rm -R "$@" will be executed.
  • If find finds something the current shell/script is killed ($$ stores the pid). The rm-part will never be executed in this case.
5
  • Hi -- that's a neat trick! I'll wait and see if there's another answer though.
    – jamadagni
    Sep 19, 2014 at 7:34
  • ... and it's limited to stopping the current script and doesn't allow to output an exit status, does it?
    – jamadagni
    Sep 19, 2014 at 8:13
  • If the rm part is executed the command returns the exit status of rm (0, 1 or 2). If it's killed the return value $? (of the script) is 137 (see tldp.org/LDP/abs/html/exitcodes.html) 137 means 128+9 that the script is killed by signal #9 (SIGKILL).
    – chaos
    Sep 19, 2014 at 8:38
  • @jamadagni You can trap the signal if you want to change the exit status. Sep 19, 2014 at 21:33
  • @chaos: I'm sure a killed app will have an exit status. I meant about controlling the exit status like Gilles said. @Gilles: Thanks. Using trap "exit 1" SIGKILL does fine.
    – jamadagni
    Sep 25, 2014 at 13:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .