PostHeaderIcon Shell script: como fazer um loop até que uma tecla seja pressionada?

Recentemente, um amigo me mandou um email com uma dúvida: ele precisava desenvolver um shell script que ficasse executando uma determinada tarefa até que uma tecla pré-estabelecida fosse pressionada. Por imaginar que essa pode ser a necessidade de muitos outros sysadmins, usuários e desenvolvedores que trabalham com o mundo GNU/Linux, resolvi compartilhar essa rápida discussão por aqui.

Bem, existem várias maneiras para resolver esse problema e resolvi indicar uma das formas que julgo ser de fácil e rápido entendimento. O ponto chave é utilizar o comando read. Vejamos o exemplo a seguir:

#!/bin/bash
while read MyKey; do
        if [ "$MyKey" == "p" ]; then
                echo "Tecla escolhida foi pressionada. Saindo do loop."
                break
        fi

        # // Inclua aqui comandos a serem executados...
        # // ...enquanto a tecla nao e pressionada
        echo "Minhas tarefas estao sendo executadas"

done
echo "Fim."

Bem, isso não parece resolver o problema, certo? Isso porque as tarefas devem ficar sendo executadas enquanto uma tecla pré-determinada (nesse caso, “p”), não for pressionada. Por outro lado, no exemplo anterior, as tarefas serão executadas apenas quando uma tecla qualquer, que não seja o próprio “p”, for pressionada. Isso ocorre porque o comando “read” ficará aguardando indefinidamente que o usuário digite alguma tecla que, por sua vez, é inserida na variável MyKey . Bem, definitivamente, não é disso que precisamos, certo?

Poucas pessoas sabem, mas o comando read não precisa ficar aguardando infinitamente alguma entrada do usuário. Com o parâmetro “-t <seg>” você pode indicar quantos segundos o comando irá ficar aguardando para que algo seja digitado. Caso o tempo indicado, em segundos, expire e nada seja digitado, o comando encerra sua execução. Sabendo disso, algumas pequenas mudanças nos farão chegar onde precisamos:

#!/bin/bash
while true ; do          
        read -n 1 -t 1 MyKey
        if [ "$MyKey" == "p" ]; then
                echo "Tecla escolhida foi pressionada. Saindo do loop."
                break
        fi

        # // Inclua aqui comandos a serem executados
        # // ...enquanto a tecla nao e pressionada
        echo "Minhas tarefas estao sendo executadas"
done
echo "Fim."

Feito, não? Entretanto, para ser um pouco mais caprichoso com o exemplo, ainda é possível alterar um “pouquinho  mais” o exemplo:

#!/bin/bash
INTERVALO=2 
while true ; do          
        read -s -n 1 -t $INTERVALO MyKey
        if [ "$MyKey" == "p" ]; then
                echo "Tecla escolhida foi pressionada. Saindo do loop."
                break
        fi

        # // Inclua aqui comandos a serem executados...
        # // ...enquanto a tecla nao e pressionada
        echo "Minhas tarefas estao sendo executadas"
done
echo "Fim."

Duas pequenas mudanças, certo? A primeira, muito básica, consiste em colocar o intervalo de tempo do read em uma variável. Dependendo do script, isso pode ajudar para mudar o comportamento sem entrar muito no código. A segunda, igualmente simples, consiste na adição do parâmetro “-s” que faz com que a tecla pressionada pelo usuário não seja impressa no terminal. Puro capricho… :-)

Acho que é isso. Até a próxima!

Leave a Reply