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.

  • possible duplicate of How to stop the find command after first match? – cuonglm Sep 19 '14 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 '14 at 4:12
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.
  • Hi -- that's a neat trick! I'll wait and see if there's another answer though. – jamadagni Sep 19 '14 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 '14 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 '14 at 8:38
  • @jamadagni You can trap the signal if you want to change the exit status. – Gilles Sep 19 '14 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 '14 at 13:17

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.