Como executo um comando e obtenho seu código de saída em menos caracteres?

13

Eu costumava escrever meus scripts assim:

some_command
while [ $? -ne 0 ] ; do
    sleep 1
    some_command
done

Sempre me irritava ter que escrever some_commandduas vezes. Posso colocá-lo dentro da seção de teste de loop de alguma forma?

Mihai
fonte

Respostas:

20

Você pode usar some_commandcomo sua condição de teste.

while ! some_command; do sleep 1; done

A condição permanecerá verdadeira enquanto some_commandsair com um erro.

Ou uma maneira mais detalhada, se você quiser fazer verificações adicionais:

while ! some_command
do 
    # add more if desired
    sleep 1
done
John WH Smith
fonte
Isso parece melhor do que o meu, mesmo que seja uma linha ;-) #
Anthon
O OP pode querer dividi-lo em várias linhas devem ele precisa para executar vários comandos em caso de falha, embora :)
John WH Smith
Não há razão para que você não possa quebrá-lo com ponto e vírgula para torná-lo com várias linhas.
Mark Stewart
1
... ou escrevawhile ! some_command; do several; commands; sleep 1; done
ignis
12

É para isso que serve o untilloop:

until some_command
do    sleep 1
done

É a negação lógica de um whileloop.

A especificação diz:

The untilLoop

  • O untilloop deve executar continuamente uma lista composta desde que outra lista composta tenha um status de saída diferente de zero.

  • O formato do loop até é o seguinte:

    até lista-composta-1
    faça lista-composta-2
    feito
  • A lista-composta-1 deve ser executada e, se tiver um status de saída zero, o untilcomando será concluído. Caso contrário, a lista composta 2 será executada e o processo se repetirá.
mikeserv
fonte
4

Você pode apenas fazer:

false
while [ $? -ne 0 ] ; do
   sleep 1
   some_command
done

isso tem a desvantagem de que ele sempre dorme um segundo primeiro

Se você deseja poder sair de um número de comandos para sair com 0, você pode:

while true; do
  if [ some_command ] ; then break ; fi
  if [ some_other_command ] ; then break ; fi
  sleep 1
done

o que, obviamente, também funciona por apenas some_command

Anthon
fonte
5
O segundo exemplo não deve incluir [e ]contornar os comandos.
nyuszika7h
2

Nem while ! ...nem until ...trabalhos sobre os sistemas que congelou seu ambiente shell antes POSIX.1-2001. Isso, no entanto, faz.

while :; do
    if some command; then
        break
    fi
    sleep 1
done

Se você não precisa de portabilidade total, por que está escrevendo um script de shell? É mais provável que o Perl esteja disponível que o Bash.

sleep 1 while 0 != system qw(some command);

(Como acima, sleepo comando é executado apenas se o comando falhar.)

zwol
fonte