Qual é o equivalente do Linux à pausa do DOS?

236

Eu tenho um script de shell Bash no qual gostaria de pausar a execução até o usuário pressionar uma tecla. No DOS, isso é facilmente realizado com o comando "pause". Existe um equivalente do Linux que eu possa usar no meu script?

jt.
fonte

Respostas:

329

read faz isso:

user@host:~$ read -n1 -r -p "Press any key to continue..." key
[...]
user@host:~$ 

O -n1especifica que aguarda apenas um único caractere. O -rcoloca no modo bruto, o que é necessário porque, caso contrário, se você pressionar algo como barra invertida, ele não será registrado até você pressionar a próxima tecla. O -pespecifica o prompt, que deve ser citado se contiver espaços. O keyargumento é necessário apenas se você quiser saber qual tecla eles pressionaram; nesse caso, você pode acessá-lo $key.

Se você estiver usando o Bash, também poderá especificar um tempo limite com -t, o que fará com que a leitura retorne uma falha quando uma tecla não for pressionada. Então, por exemplo:

read -t5 -n1 -r -p 'Press any key in the next five seconds...' key
if [ "$?" -eq "0" ]; then
    echo 'A key was pressed.'
else
    echo 'No key was pressed.'
fi
Jim
fonte
5
Estritamente falando, isso seria "Enter any non-NUL character to continue". Algumas teclas não enviar qualquer personagem (como Ctrl...) e algumas enviar mais de um (como F1, Home...). bashignora caracteres NUL.
Stephane Chazelas
2
Geralmente, é uma idéia melhor solicitar uma chave específica, como enter, espaço ou Y. "QUALQUER" pode ser confuso para alguns usuários; existe uma tecla TAB; portanto, nenhuma tecla QUALQUER e, com certeza, existem chaves potencialmente perigosas como ESCAPE, CTRL, CMD, botão liga / desliga etc. Isso não é mais tão relevante hoje em dia, porque hoje em dia o console geralmente é usado apenas por usuários avançados de computador que interpretam "QUALQUER tecla" corretamente. O Apple 2 Design Manual, bastante antigo, possui uma seção interessante dedicada a esse assunto ( apple2scans.net/files/1982-A2F2116-m-a2e-aiiedg.pdf ).
Gellweiler #
3
Se você, em vez usar a mensagem Press a key to continue..., em seguida, que os usuários inexperientes será capaz de encontrar a achave e pressione-o; o)
DJDaveMark
1
Isso terá problemas com command | myscript.shou myscript.sh | command. Veja esta resposta para uma solução.
Tom Hale
Se alguém conseguir read: 1: read: Illegal option -ncertificar-se de incluir seu comando, bash -c 'command && command'etc., pois é provável que esse erro ocorra sh. Estou fazendo isso em um comando de Lando wrapper.
Elias Lynn
155

Eu uso muito essas maneiras muito curtas e são como as soluções @theunamedguy e @Jim, mas com tempo limite e modo silencioso além disso.

Eu amo especialmente o último caso e o uso em muitos scripts que são executados em loop até o usuário pressionar Enter.

Comandos

  • Inserir solução

    read -rsp $'Press enter to continue...\n'
  • Solução de escape (com -d $ '\ e')

    read -rsp $'Press escape to continue...\n' -d $'\e'
  • Qualquer solução importante (com -n 1)

    read -rsp $'Press any key to continue...\n' -n 1 key
    # echo $key
    
  • Pergunta com escolha pré-selecionada (com -ei $ 'Y')

    read -rp $'Are you sure (Y/n) : ' -ei $'Y' key;
    # echo $key
    
  • Solução de tempo limite (com -t 5)

    read -rsp $'Press any key or wait 5 seconds to continue...\n' -n 1 -t 5;
  • Alias ​​aprimorado do sono

    read -rst 0.5; timeout=$?
    # echo $timeout
    

Explicação

-r especifica o modo bruto, que não permite caracteres combinados como "\" ou "^".

-s especifica o modo silencioso e porque não precisamos de saída do teclado.

-p $ ' prompt ' especifica o prompt, que precisa estar entre $ 'e' para deixar espaços e caracteres de escape. Cuidado, você deve colocar entre aspas simples com o símbolo de dólares para beneficiar caracteres que escaparam, caso contrário, poderá usar aspas simples.

-d $ ' \ e ' especifica escappe como caractere delimitador; portanto, como um caractere final para a entrada atual, é possível colocar qualquer caractere, mas tenha cuidado ao colocar um caractere que o usuário possa digitar.

-n 1 especifica que ele precisa apenas de um único caractere.

-e especifica o modo readline.

-i $ ' Y ' especifica Y como texto inicial no modo readline.

-t 5 especifica um tempo limite de 5 segundos

A tecla serve no caso de você precisar conhecer a entrada, no caso -n1, a tecla que foi pressionada.

$? serve para saber o código de saída do último programa, para leitura, 142 em caso de tempo limite, 0 entrada correta. Coloque $? em uma variável o mais rápido possível, se você precisar testá-la após alguns comandos, porque todos os comandos reescreveriam $?

y.petremann
fonte
1
+1 para explicar -s; man reade read --helpajuda não ajudou no Ubuntu 10.04.1 LTS. Editar: help readfez; o resto está obsoleto?
Cees Timmerman
1
1+ para a grande explicação: mas eu consegui read: -i: invalid optiono ex. read -rp $'Are you sure (Y/n) : ' -ei $'Y' key;em #osx read -rp $'kill-server: Are you sure (Y/n) : ' -d $'Y' key;funciona para mim. `
Tino Rüb
Não sei como funciona no OSX, mas fiz alguns testes e -ifunciona perfeitamente no Ubuntu, também não sei se -dfunciona da mesma maneira no OSX.
y.petremann
pode-se contornar prompt de realmente rápido e agradável usando um eco antes de leitura, eventualmente, echo -n
THESorcerer
15

readsem nenhum parâmetro só continuará se você pressionar enter. O pausecomando do DOS continuará se você pressionar qualquer tecla. Use read –n1se você deseja esse comportamento.

xsl
fonte
15

Isso funcionou para mim em vários sabores do Linux, onde algumas dessas outras soluções não (incluindo as mais populares aqui). Eu acho que é mais legível também ...

echo Press enter to continue; read dummy;

Observe que uma variável precisa ser fornecida como argumento para read.

BuvinJ
fonte
esta resposta resolve meu problema, se eu copiar e colar esta linha e, por algum motivo, tiver mais linhas anexadas, as linhas anexadas não serão executadas, como ocorreu com a pausa do DOS
Sérgio
10

read -n1não é portátil. Uma maneira portátil de fazer o mesmo pode ser:

(   trap "stty $(stty -g;stty -icanon)" EXIT
    LC_ALL=C dd bs=1 count=1 >/dev/null 2>&1
)   </dev/tty

Além de usar read, para pressionar apenas ENTERpara continuar, você pode:

sed -n q </dev/tty
mikeserv
fonte
2
status=nonetambém não é portátil. Redirecione stdout e stderr para / dev / null. read -r line < /dev/ttyseria enought para pressionar ENTER ... .
Stephane Chazelas
@StephaneChezales thanks - eu não sabia disso. vou consertar agora. Mais uma vez obrigado - corrigido. Você é um poço sem fundo de informações que valem a pena.
mikeserv
1
Observe também settings=$(stty -g); stty raw; dd ...; stty "$settings"para salvar e restaurar as configurações de tty.
Stephane Chazelas
@StephaneChezales - não estou em um computador - você acha que a tredição também poderia funcionar?
mikeserv
1
Não, porque trarmazenaria em buffer sua saída como um tubo, e os teclados de fora dos EUA têm teclas que enviam caracteres fora do \1-\177intervalo. ddé a maneira idiomática aqui.
Stephane Chazelas
2

Se você apenas precisar pausar um loop ou script, e estiver feliz em pressionar Enter em vez de qualquer tecla, readpor si só fará o trabalho.

do_stuff
read
do_more_stuff

Não é fácil para o usuário final, mas pode ser suficiente nos casos em que você está escrevendo um script rápido e precisa pausá-lo para fazer algo manualmente em segundo plano.

mwfearnley
fonte
Isso é verdade, mas para o banco de dados é mais útil mostrar um exemplo.
SDsolar 27/03
Obrigado, aceitei o seu conselho. Apenas escrever um nome de comando não é muito claro em retrospectiva.
Mwfearnley #
1

Tente o seguinte:

function pause(){
   read -p "$*"
}
Alex Fort
fonte
1
Alguém pode explicar por que isso foi prejudicado? É por falta de conteúdo ou é uma solução ruim?
3ocene 11/04
4
@ 3ocene Isto não mostra a utilização da função criada; além disso, falta uma explicação.
parvus
Acordado. Você pode mostrar um exemplo de como essa função é chamada?
SDsolar
1

Esta função funciona em ambos bashe zsh, e garante I / O para o terminal:

# Prompt for a keypress to continue. Customise prompt with $*
function pause {
  >/dev/tty printf '%s' "${*:-Press any key to continue... }"
  [[ $ZSH_VERSION ]] && read -krs  # Use -u0 to read from STDIN
  [[ $BASH_VERSION ]] && </dev/tty read -rsn1
  printf '\n'
}
export_function pause

Coloque-o no seu .{ba,z}shrcpara Grande Justiça!

Tom Hale
fonte
0

Sim para usar read- e há alguns ajustes que o tornam mais útil nos cronterminais e no terminal.

Exemplo:

time rsync (options)
read -n 120 -p "Press 'Enter' to continue..." ; echo " "

O -n 120 faz o tempo limite da instrução de leitura expirar após 2 minutos, para que não seja bloqueado cron.

No terminal, ele fornece 2 minutos para ver quanto tempo o rsynccomando levou para executar.

Então o subsequente echoé para que o prompt do bash subseqüente apareça na próxima linha.

Caso contrário, será exibido na mesma linha diretamente após "continuar ..." quando Enterfor pressionado no terminal.

SDsolar
fonte