26

I'm setting up a shell script with menues and sub menues, options, etc. But on each menu/submenu/etc, i need a "Go back to main menu" choice.

I've already got the menu set up and it works fine, but i need a way to simply restart the script from scratch, reset all variables etc etc.

Or a way to exit the current script and starting it again.

I've tried to do this:

ScriptLoc=$(readlink -f "$0")
./ScriptLoc

But that starts the "new" script inside the "old" script, so when i exit the "new" script, it goes back to the "old" script (if that makes any sense). It's a script inside a script kind of thing.

Anyone got an idea how to restart it completely?

1
  • That should be $ScriptLoc anyhow: ./ScriptLoc looks for a script of that name in the current directory.
    – poolie
    Oct 14, 2013 at 0:08

3 Answers 3

28

Yes, do

exec "$ScriptLoc"

The exec bash builtin command replaces the current program with a new one.

11

You can use something like this:

$(basename $0) && exit

$(basename $0) will create a new instance of the current script and exit will exit from the curent instance of the script.

Here is a test script that highlights the above method:

#!/bin/bash

if ! [[ $count =~ ^[0-9]+$ ]] ; then
    export count=0
fi

echo $count

if [ $count -le 10 ]; then
    count=$(echo "$count+1" | bc)   
    ./$(basename $0) && exit #this will run if started from the same folder
fi

echo "This will be printed only when the tenth instance of script is reached"

If you don't use export count=0 (which make count to be an environment variable) and use only count=0 (which make cont a local script variable), then the script will never stop.

2
  • && exit will exit only if the script succeeds. So if for example the script is not executable or has a syntax error, this is likely to just spin.
    – poolie
    Oct 16, 2013 at 0:48
  • Added ./ to the basename - otherwise a beautiful solution - really nice, def a +1. Mar 7, 2017 at 10:59
4

Reliably getting the script that's currently executing is harder than you might think. See http://mywiki.wooledge.org/BashFAQ/028.

Instead, you could do something like this:

main_menu() { 
    printf '1. Do something cool\n'
    printf '2. Do something awesome\n'
    : ... etc
}

some_sub_sub_menu() {
    ...
    printf 'X. Return to main menu\n'
    ...
    if [[ $choice = [Xx] ]]; then
        exit 255
    fi
}

while true; do
    (main_menu)
    res=$?
    if (( res != 255 )); then
        break
    fi
done

Basicly, you run the main_menu function in a subshell, so if you exit from the main_menu, or any of the sub menus, you exit the subshell, not the main shell. exit status 255 is chosen here to mean "go again". Any other exit status will break out of the otherwise infinite loop.

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.