Como reiniciar completamente o script de dentro do próprio script

22

Estou configurando um script de shell com menus e submenus, opções etc. Mas em cada menu / submenu / etc, preciso da opção "Voltar ao menu principal".

Eu já tenho o menu configurado e funciona bem, mas preciso de uma maneira de simplesmente reiniciar o script do zero, redefinir todas as variáveis, etc.

Ou uma maneira de sair do script atual e iniciá-lo novamente.

Eu tentei fazer isso:

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

Mas isso inicia o script "novo" dentro do script "antigo", portanto, quando eu saio do script "novo", ele volta ao script "antigo" (se isso faz algum sentido). É um script dentro de um tipo de coisa de script.

Alguém tem uma idéia de como reiniciá-lo completamente?

Moonbloom
fonte
De $ScriptLocqualquer forma, isso deve ser : ./ScriptLocprocura um script com esse nome no diretório atual.
poolieby

Respostas:

10

Você pode usar algo como isto:

$(basename $0) && exit

$(basename $0)criará uma nova instância do script atual e exitsairá da instância atual do script.

Aqui está um script de teste que destaca o método acima:

#!/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"

Se você não usar export count=0(o que torna countuma variável de ambiente) e usar apenas count=0(que torna contum script local variável), o script nunca será interrompido.

Radu Rădeanu
fonte
&& exitsairá somente se o script for bem-sucedido. Portanto, se, por exemplo, o script não for executável ou apresentar um erro de sintaxe, é provável que ele gire.
Pool16:
Adicionado ./ ao nome da base - caso contrário, uma solução bonita - muito bom, def um +1.
precisa
4

Obter o script que está sendo executado de maneira confiável é mais difícil do que você imagina. Veja http://mywiki.wooledge.org/BashFAQ/028 .

Em vez disso, você poderia fazer algo assim:

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

Basicamente, você executa a função main_menu em um subshell; portanto, se você sair do main_menu ou de qualquer um dos submenus, sai do subshell, não do shell principal. o status de saída 255 é escolhido aqui para significar "ir novamente". Qualquer outro status de saída sairá do loop infinito.

Geirha
fonte