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!



Parabéns pelo artigo. Está super bem explicado.
Obrigado, Heloisa. Espero que o post tenha sido, de alguma maneira, útil para você.
Abraço,
Jansen Sena