Como fazer algo condicionalmente se um comando foi bem-sucedido ou falhou

Como posso fazer algo assim no bash?

if "`command` returns any error"; then echo "Returned an error" else echo "Proceed..." fi 

Resposta

Como fazer algo condicionalmente se um comando teve sucesso ou falhou

Isso é exatamente o que o bash A instrução “s if faz:

if command ; then echo "Command succeeded" else echo "Command failed" fi 

Adicionando informações de comentários: você don” t precisa usar a sintaxe [] neste caso. [ é em si um comando, quase equivalente a test. É provavelmente o comando mais comum para usar em um if, que pode levar partindo do pressuposto de que é parte da sintaxe do shell. Mas se você quiser testar se um comando foi bem-sucedido ou não, use o próprio comando diretamente com if, conforme mostrado acima.

Comentários

  • Observe que o ponto-e-vírgula é importante.
  • Ou você pode simplesmente colocar then em uma linha separada.
  • @Joe: Acho que você quer dizer if ! command ; then ... ; fi. [ é em si um comando e ‘ não é necessário neste caso.
  • @Joe: My way também tem a virtude de ser correto. if [ ! command ] não ‘ t executa command; ele trata command como uma string e o trata como verdadeiro porque tem um comprimento diferente de zero. [ é um sinônimo para o comando test
  • Ops. Você ‘ está correto.

Resposta

Para pequenas coisas que você deseja que aconteça se um comando shell funcionar, você pode usar a construção &&:

rm -rf somedir && trace_output "Removed the directory" 

Da mesma forma para pequenas coisas que você deseja que aconteçam quando um comando shell falha, você pode usar ||:

rm -rf somedir || exit_on_error "Failed to remove the directory" 

Ou ambos

rm -rf somedir && trace_output "Removed the directory" || exit_on_error "Failed to remove the directory" 

Provavelmente não é aconselhável fazer muito com essas construções, mas às vezes elas podem tornar o fluxo de controle muito mais claro.

Comentários

  • Eles são mais curtos e (pelo menos em alguns shells) mais rápidos. Estremeço ao lembrar de um script de instalação do Ultrix monstro escrito apenas com essas construções condicionais que tentei uma vez decifrar …

Resposta

Verifique o valor de $?, que contém o resultado da execução do comando / função mais recente:

#!/bin/bash echo "this will work" RESULT=$? if [ $RESULT -eq 0 ]; then echo success else echo failed fi if [ $RESULT == 0 ]; then echo success 2 else echo failed 2 fi 

Comentários

  • Embora tecnicamente correto (e, portanto, não justifique um voto negativo), ‘ não está usando o idioma Bash ‘ s if. Prefiro a resposta de Keith Thompson ‘.
  • Esse idioma traz benefícios – ele preserva o valor de retorno. Ao todo, acho este mais poderoso, embora mais prolixo. é ‘ também mais fácil de ler.
  • O que é ” Bash ‘ s if idiom “?
  • @Nowaker O fato de que o único propósito de if é fazer esta. Todas as condições de controle de fluxo no Bash examinam $? nos bastidores; isso ‘ é o que eles fazem. Examinar explicitamente seu valor deve ser desnecessário na grande maioria dos casos e geralmente é um antipadrão iniciante.
  • Prefiro isso para facilitar a leitura. O comando principal é normalmente muito longo. Colocá-lo dentro de uma instrução ” if ” torna a legibilidade ruim.

Resposta

Isso funcionou para mim:

command && echo "OK" || echo "NOK" 

if command for bem-sucedido, echo "OK" é executado e, como foi bem-sucedido, a execução para aí. Caso contrário, && é ignorado e echo "NOK" é executado.

Comentários

  • Se você quiser fazer algo se falhar, e preservar o código de saída (para mostrar no prompt de comando ou testar em um script), você pode fazer isso: command && echo "OK" || c=$?; echo "NOK"; $(exit $c)
  • @ Sam-Hasler: shouldn ‘ t que seja command && echo "OK" || (c=$?; echo "NOK"; (exit $c))?
  • Além disso, se a parte echo "OK" pudesse ela mesma falhar, então é melhor: command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
  • @ jrw32982, Legal, eu ‘ usei a construção anterior, mas não o último.
  • A verdadeira resposta está nos comentários, obrigado a todos!

Resposta

Deve-se observar que if...then...fi e && / || tipo de abordagem lida com o status de saída retornado pelo comando que desejamos testar (0 em caso de sucesso); no entanto, alguns comandos não retornam um status de saída diferente de zero se o comando falhou ou não conseguiu lidar com a entrada. Isso significa que as abordagens if e && / || usuais não funcionarão para aqueles comandos específicos.

Por exemplo, no Linux GNU file ainda sai com 0 se recebeu um arquivo não existente como argumento e find não foi possível localizar o arquivo especificado pelo usuário.

$ find . -name "not_existing_file" $ echo $? 0 $ file ./not_existing_file ./not_existing_file: cannot open `./not_existing_file" (No such file or directory) $ echo $? 0 

Nesses casos, uma forma potencial de lidar com a situação é lendo stderr / stdin mensagens, por exemplo aqueles que retornaram pelo comando file, ou analise a saída do comando como em find. Para esse propósito, a instrução case pode ser usada.

$ file ./doesntexist | while IFS= read -r output; do > case "$output" in > *"No such file or directory"*) printf "%s\n" "This will show up if failed";; > *) printf "%s\n" "This will show up if succeeded" ;; > esac > done This will show up if failed $ find . -name "doesn"texist" | if ! read IFS= out; then echo "File not found"; fi File not found 

Resposta

O mais sujeito a erros que eu poderia inventar foi:

  • Primeiro, obtenha o valor. Suponha que você faça algo como:

RR=$?

Agora, não apenas para esta situação, mas outras que você pode enfrentar, considere:

variável definida:

$ AA=1 ; if (( "10#0${AA}" == 1 )) ; then echo yes ; else echo no ; fi

Resposta: sim

$ AA=1 ; if (( "10#0${AA}" != 1 )) ; then echo yes ; else echo no ; fi

Resposta: não

variável indefinida:

$ AA=1 ; if (( "10#0${BB}" == 1 )) ; then echo yes ; else echo no ; fi

Resposta: não

$ AA=1 ; if (( "10#0${BB}" != 1 )) ; then echo yes ; else echo no ; fi

Resposta: sim

$ AA=1 ; if (( "10#0${BB}" == 0 )) ; then echo yes ; else echo no ; fi

Resposta: sim

Isso evita todos os tipos de erros.

Você provavelmente conhece toda a sintaxe, mas aqui alguns dicas:

  • Use aspas. Evite que "blank" seja nothing.
  • A nova notação moderna para variáveis é ${variable}.
  • Adicionar um zero concatenado antes do seu número também evita “nenhum número”.
  • Mas espere, adicionar um zero torna o número base-8. Você receberá um erro como:
    • value too great for base (error token is "08") para números acima de 7. É quando 10# entra em jogo:
    • 10# força o número a ser base-10.

Resposta

Você pode fazer isso:

if ($( ping 4.4.4.4 -c1 > /dev/null )) ; then echo "ping response succsess!!!" fi 

Comentários

  • Isso funciona, mas é complicado. Você ‘ está executando o ping em um subshell de um subshell, a saída de ping é capturada para executá-lo como um comando. Mas como a saída é redirecionada para / dev / null, essa sempre será a string vazia. Portanto, você ‘ não está executando nada em um subshell, o que significa que o status de saída anterior (do subshell de substituição de comando, ou seja, ping) será mantido. Obviamente, a maneira correta é if ping ...; then aqui.

Resposta

Conforme observado em outro lugar neste tópico, a pergunta original basicamente responde a si mesma. Aqui está uma ilustração mostrando que as if condições também podem ser aninhadas.

Este exemplo usa if para verificar se um arquivo existe e se é um arquivo normal. Se essas condições forem verdadeiras, verifique se ele tem ou não um tamanho maior que 0.

#!/bin/bash echo "Which error log are you checking today? " read answer if [ -f /opt/logs/$answer*.errors ] then if [ -s /opt/logs/$answer*.errors ] then echo "Content is present in the $answer error log file." else echo "No errors are present in the $answer error log file." fi else echo "$answer does not have an error log at this time." fi 

Comentários

  • Isso é o que sua resposta faz, mas sua resposta não aborda a questão.
  • @JeffSchaller, obrigado por sua observação. Editei minha postagem para incluir uma referência à pergunta.

Resposta

#!/bin/bash if command-1 ; then echo "command-1 succeeded and now running from this block command-2" command-2 else echo "command-1 failed and now running from this block command-3" command-3 fi 

Comentários

Resposta

Isso poderia ser feito simplesmente desta forma, já que $? fornece o status do último comando executado.

Portanto, pode ser

#!/bin/sh ... some command ... if [ $? == 0 ] ; then echo "<the output message you want to display>" else echo "<failure message>" fi 

Comentários

  • Votar negativamente: Isso simplesmente parafraseia uma resposta anterior que recebeu críticas por ser unidiomática.
  • Na verdade, era exatamente isso que eu procurava porque ‘ estou tentando para fazer com que o ” comando ” falhe no script como parte de ” set -e ” que não ‘ t se ‘ faz parte do if.Isso não deve ser ‘ não votado.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *