Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

If I have a series of nested functions, how can I break out of all of them from the innermost function?

EDIT: Busy looking into the builtin 'trap'...

share|improve this question
    
Functions can't be nested in shell. There are no closures. Did you mean break out of all but the outermost scope? Innermost doesn't make sense. – ormaaj Mar 6 '13 at 16:48
    
@ormaaj: All of them from the innermost function. – Dennis Mar 6 '13 at 16:50
    
Ahh ok, gotcha. – ormaaj Mar 6 '13 at 16:54

A rather ugly but easy way to achieve this would be defining STOP variable and checking it after every function call:

a ()
{
    echo a
    b; [[ "$STOP" == 1 ]] && return
    a; [[ "$STOP" == 1 ]] && return
}

b ()
{
    echo b
    c; [[ "$STOP" == 1 ]] && return
    b; [[ "$STOP" == 1 ]] && return
}

c ()
{
    echo c
    STOP=1; return
}

a
echo d

Not pretty, but it works in bash and zsh.

share|improve this answer

Here's a not-necessarily-portable hack that jumps out of all the required levels bypassing all RETURN traps, effectively prevents returning anything but 0, and is possibly a bug in at least some respects. This particular implementation is Bash-only but can be adapted to other shells.

function f {
    printf 'Current level: %d\n' ${n:+"$1"}
    if [[ $FUNCNAME != "${FUNCNAME[1]}" ]]; then
        [[ $1 == +([[:digit:]]) ]] || return 1
        typeset n=$1
        while ! f 1; do :; done
        unset -v n
    elif (( n - $1 )); then
        f $(($1 + 1))
    else
        trap 'printf "Returning from level: %d\n" ${n+"$1"}' RETURN
        # return # toggle
        break
    fi
}

f "${1:-5}"

output

Current level: 0
Current level: 1
Current level: 2
Current level: 3
Current level: 4
Current level: 5
Returning from level: 0
share|improve this answer

I went with storing all the logic in a separate shell script instead of using functions. Exit will break out of the script entirely and allow your wrapper script to continue execution.

share|improve this answer

You must log in to answer this question.

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