16

I have a bash script, where I call exit somewhere to skip the rest of the script when getopts doesn't recognize an option or doesn't find an expected option argument.

while getopts ":t:" opt; do
    case $opt in
        t)
            timelen="$OPTARG"
            ;;
        \?) printf "illegal option: -%s\n" "$OPTARG" >&2
            echo "$usage" >&2
            exit 1
            ;;
        :) printf "missing argument for -%s\n" "$OPTARG" >&2
           echo "$usage" >&2
           exit 1
           ;;
    esac
done

# reset of the script

I source the script in a bash shell. When something is wrong, the shell exits.

Is there some way other than exit to skip the rest of the script but without exiting the invoking shell?

Replacing exit with return doesn't work like for a function call, and the rest of the script will runs.

Thanks.

5
  • Hmm? return seems to work for me. If I have a script echo hello ; return ; echo there then source it I only get the hello output. Commented Aug 2, 2018 at 15:38
  • Thanks, @StephenHarris I made a mistake. I use exit inside a while loop. I guess replacing it with return only exits the while loop, but continue to run the rest of the program after the while loop. How can I skip the rest of the program then?
    – Tim
    Commented Aug 2, 2018 at 16:21
  • @Tim break exits a loop, return exits a function or a sourced script.
    – Kusalananda
    Commented Aug 2, 2018 at 16:24
  • 1
    @Tim, why do you source it instead of executing it? Commented Aug 2, 2018 at 16:25
  • Additional details: How can I tell whether my script was sourced (dotted in) or executed? Commented Aug 2, 2018 at 16:30

4 Answers 4

15

Use return.

The return bash builtin will exit the sourced script without stopping the calling (parent/sourcing) script.

From man bash:

return [n]
Causes a function to stop executing and return the value specified by n to its caller. If n is omitted, the return status is that of the last command executed in the function body. … If return is used outside a function, but during execution of a script by the . (source) command, it causes the shell to stop executing that script and return either n or the exit status of the last command executed within the script as the exit status of the script.

2
  • Thanks. Do return [n] and exit n work the same except in a function or a script being sourced?
    – Tim
    Commented Aug 2, 2018 at 17:01
  • No, a return is never an exit. An exit will "get out" of the running script (shell). A return will stop reading (and executing) either a sourced file or a function. A return outside a function and outside a sourced file will be reported as an error by bash. An exit (almost) never will be an error and will "stop all processing". @Tim
    – user232326
    Commented Aug 2, 2018 at 17:06
8

You could simply wrap your script in a function and then use return the way you describe.

#!/bin/bash
main () {
    # Start of script
    if [ <condition> ]; then
        return
    fi
    # Rest of the script will not run if returned
}

main "$@"
2

return exits sourced scripts (and functions).

In your case:

while getopts ":t:" opt; do
    case $opt in
        t)
            timelen="$OPTARG"
            ;;
        \?) printf "illegal option: -%s\n" "$OPTARG" >&2
            echo "$usage" >&2
            return 1
            ;;
        :) printf "missing argument for -%s\n" "$OPTARG" >&2
           echo "$usage" >&2
           return 1
           ;;
    esac
done

Example test:

$ cat script1.sh
echo script1
source ./script2.sh
echo script1 ends
$ cat script2.sh
echo script2

while true; do
    return
done

echo script2 ends
$ bash script1.sh
script1
script2
script1 ends

Also sourcing script2.sh directly does the correct thing (without exiting from the current shell session):

$ source script2.sh
script2
1

In some cases I will want to allow exit except if I'm at the first shell, so I use this:

if [[ $SHLVL -gt 1 ]]; then exit 0; fi
2
  • This works in the context I want (a called script called without source) without haggling complexity of using source or setting up to use return, and is much more elegant in my opinion. Commented Aug 25 at 2:55
  • That damned haggling complexity.... "2 for that, you must be mad!?!!"
    – Engineer
    Commented Aug 25 at 3:00

You must log in to answer this question.

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