How can I skip the rest of a script without exiting the invoking shell, when sourcing the script?

12,546

Solution 1

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.

Solution 2

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 "$@"

Solution 3

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
Share:
12,546

Related videos on Youtube

Tim
Author by

Tim

Elitists are oppressive, anti-intellectual, ultra-conservative, and cancerous to the society, environment, and humanity. Please help make Stack Exchange a better place. Expose elite supremacy, elitist brutality, and moderation injustice to https://stackoverflow.com/contact (complicit community managers), in comments, to meta, outside Stack Exchange, and by legal actions. Push back and don't let them normalize their behaviors. Changes always happen from the bottom up. Thank you very much! Just a curious self learner. Almost always upvote replies. Thanks for enlightenment! Meanwhile, Corruption and abuses have been rampantly coming from elitists. Supportive comments have been removed and attacks are kept to control the direction of discourse. Outright vicious comments have been removed only to conceal atrocities. Systematic discrimination has been made into policies. Countless users have been harassed, persecuted, and suffocated. Q&amp;A sites are for everyone to learn and grow, not for elitists to indulge abusive oppression, and cover up for each other. https://softwareengineering.stackexchange.com/posts/419086/revisions https://math.meta.stackexchange.com/q/32539/ (https://i.stack.imgur.com/4knYh.png) and https://math.meta.stackexchange.com/q/32548/ (https://i.stack.imgur.com/9gaZ2.png) https://meta.stackexchange.com/posts/353417/timeline (The moderators defended continuous harassment comments showing no reading and understanding of my post) https://cs.stackexchange.com/posts/125651/timeline (a PLT academic had trouble with the books I am reading and disparaged my self learning posts, and a moderator with long abusive history added more insults.) https://stackoverflow.com/posts/61679659/revisions (homework libels) Much more that have happened.

Updated on September 18, 2022

Comments

  • Tim
    Tim almost 2 years

    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.

    • Stephen Harris
      Stephen Harris almost 6 years
      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.
    • Tim
      Tim almost 6 years
      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?
    • Kusalananda
      Kusalananda almost 6 years
      @Tim break exits a loop, return exits a function or a sourced script.
    • Angel Todorov
      Angel Todorov almost 6 years
      @Tim, why do you source it instead of executing it?
    • Angel Todorov
      Angel Todorov almost 6 years
  • Tim
    Tim almost 6 years
    Thanks. Do return [n] and exit n work the same except in a function or a script being sourced?
  • done
    done almost 6 years
    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