I have a script looks like:

for f in */*; do
cp -v "$f" "/myhome/CE$(printf '%0*d' 2 $BATCHNUM)-new-stuctures_extracted/test-$(printf '%0*d' 5 $c)"

However, the user must provide a variable call BATCHNUM and otherwise I need to force this script stop running. It will be better if I could force the script that calls this script to stop too (or even the #1 script that calls #2 script which calls this script).


The quickest way is probably to add these two lines to the start of the script:

set -u # or set -o nounset

The first line sets the nounset option in the shell running the script, which aborts if you try to expand an unset variable; the second expands $BATCHNUM in the context of a no-op, to trigger the abort before doing anything else.

If you want a more helpful error message, you could instead write:

if [[ -z "$BATCHNUM" ]]; then
    echo "Must provide BATCHNUM in environment" 1>&2
    exit 1

Or similar.


Here you want to check BATCHNUM is set and not null.

POSIX shell provide a Parameter Expansion for this job. Just adding this line before using BATCHNUM:

: "${BATCHNUM:?Variable not set or empty}"

or better to set the default value for BATCHNUM if user didn't provide one:

: "${BATCHNUM:=3}"
  • How to make ${x:?} return non-zero in case of failure? – HappyFace Mar 12 at 14:20
  • @HappyFace it does return non-zero in case of failure already. – cuonglm Mar 15 at 2:23
[ -n "$BATCHNUM" ] || { kill "$PPID"; exit 1; }
#Unless $BATCHNUM is defined and unempty, ask parent process to exit and exit w/ 1

This will work on bash and in a POSIX sh. I prefer not to differentiate between empty variables and undefined variables (i.e., I don't like set -u, but that's just me).


The lines

if [ -z "$BATCHNUM" ]; then
    exit 2;

check for empty $BATCHNUM. With $PPID you can do whatever harm you want to your parent (kill $PPID). For murdering your grandparent, you need to get the process id by other means, like looking at the data in /proc/$PPID.

However, if your parent dies, it sends a signal (SIGHUP) to you, so you have to trap it before you start killing anybody:

trap '' SIGHUP

Update: If you think you have to kill your parents, you doing it wrong. Just return a meaningfull exitcode. The parent script should check the called script's return code and react accordingly.

  • 1
    a bit brutal.... :) – user40780 Sep 8 '15 at 16:34

To test if BATCHNUM is defined, and exit if it isn't:

if [ -n "${BATCHNUM-a}" ]; then
  echo >&2 "Fatal error: BATCHNUM not set"
  exit 2

If you also want to reject the case where BATCHNUM is empty, use ${BATCHNUM:+a} instead of ${BATCHNUM+a}. For information about the ${VARIABLE+TEXT_IF_NULL} parameter expansion construct, see e.g. the bash manual.

Don't kill the parent process. You don't know what the parent process is. If some script that calls this one needs to abort if this script aborts, make it check the exit status of this script. E.g. in script #2:

script3 || exit $?

or use set -e to abort the script if any command returns a failure (nonzero) status.

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.