Cómo hacer algo condicionalmente si un comando tuvo éxito o falló

¿Cómo puedo hacer algo como esto en bash?

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

Respuesta

Cómo hacer algo condicionalmente si un comando tuvo éxito o falló

Eso es exactamente lo que bash «s if declaración hace:

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

Agregar información de comentarios: usted no» t necesita usar la sintaxis [] en este caso. [ es en sí mismo un comando, casi equivalente a test. Es probablemente el comando más común para usar en un if, que puede conducir a la suposición de que es parte de la sintaxis del shell. Pero si desea probar si un comando tuvo éxito o no, use el comando en sí directamente con if, como se muestra arriba.

Comentarios

  • Tenga en cuenta que el punto y coma es importante.
  • O simplemente puede poner then en una línea separada.
  • @Joe: Creo que te refieres a if ! command ; then ... ; fi. [ es en sí mismo un comando, y ‘ no es necesario en este caso.
  • @Joe: A mi manera también tiene la virtud de ser correcto. if [ ! command ] no ‘ t ejecuta command; trata command como una cadena y la trata como verdadera porque tiene una longitud distinta de cero. [ es un sinónimo del comando test
  • Vaya. ‘ estás en lo correcto.

Responder

Para pequeñas cosas que desea que suceda si un comando de shell funciona, puede usar la construcción &&:

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

De manera similar para pequeñas cosas que desea que sucedan cuando falla un comando de shell, puede usar ||:

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

O ambos

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

Probablemente no sea prudente hacer mucho con estas construcciones, pero en ocasiones pueden hacer que el flujo de control sea mucho más claro.

Comentarios

  • Son más cortos y (al menos en algunos shells) más rápidos. Me estremezco al recordar un script de instalación de Ultrix monstruoso escrito solo con estas construcciones condicionales que una vez intenté descifrar …

Responder

Verifica el valor de $?, que contiene el resultado de ejecutar el comando / función más reciente:

#!/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 

Comentarios

  • Si bien es técnicamente correcto (y por lo tanto no justifica un voto negativo), ‘ no utiliza el idioma ‘ s if de Bash. Prefiero la respuesta de Keith Thompson ‘.
  • Hay beneficios en este idioma: conserva el valor de retorno. En general, encuentro que este es más poderoso, aunque más detallado. ‘ también es más fácil de leer.
  • ¿Qué es » Bash ‘ s if idiom «?
  • @Nowaker El hecho de que el único propósito de if es hacer esta. Todas las condiciones de control de flujo en Bash examinan $? detrás de escena; que ‘ es lo que hacen. Examinar explícitamente su valor debería ser innecesario en la gran mayoría de los casos, y suele ser un antipatrón para principiantes.
  • Prefiero esto por legibilidad. El comando principal suele ser muy largo. Ponerlo dentro de una instrucción » if » hace que la legibilidad sea mala.

Respuesta

Esto funcionó para mí:

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

if command tiene éxito, luego echo "OK" se ejecuta y, dado que tiene éxito, la ejecución se detiene allí. De lo contrario, && se omite y echo "NOK" se ejecuta.

Comentarios

  • Si desea hacer algo si falla, y conservar el código de salida (para mostrar en el símbolo del sistema o probar en un script), puede hacer esto: command && echo "OK" || c=$?; echo "NOK"; $(exit $c)
  • @ Sam-Hasler: shouldn ‘ t que sea command && echo "OK" || (c=$?; echo "NOK"; (exit $c))?
  • Además, si la parte echo "OK" pudiera falla, entonces esto es mejor: command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
  • @ jrw32982, Niza, ‘ he usado la construcción anterior, pero no el último.
  • La verdadera respuesta está en los comentarios, ¡gracias a todos!

Respuesta

Cabe señalar que if...then...fi y && / || tipo de enfoque se ocupa del estado de salida devuelto por el comando que queremos probar (0 en caso de éxito); sin embargo, algunos comandos no devuelven un estado de salida distinto de cero si el comando falló o no pudo manejar la entrada. Esto significa que los enfoques if y && / || habituales no funcionarán para esos comandos particulares.

Por ejemplo, en Linux GNU file todavía sale con 0 si recibió un archivo no existente como argumento y find no se pudo localizar el archivo especificado por el usuario.

$ 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 

En tales casos, una forma potencial de manejar la situación es leyendo stderr / stdin mensajes, p. ej. los que devolvió el comando file, o analizar la salida del comando como en find. Para ello, se podría utilizar la instrucción case.

$ 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 

Respuesta

El más propenso a errores que se me ocurrió fue:

  • Primero, obtenga el valor. Suponga que hace algo como:

RR=$?

Ahora, no solo para esta situación, sino para otras que puede enfrentar, considere:

variable definida:

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

Respuesta: sí

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

Respuesta: no

variable indefinida:

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

Respuesta: no

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

Respuesta: sí

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

Respuesta: sí

Esto evita todo tipo de errores.

Probablemente conozca toda la sintaxis, pero aquí algunos consejos:

  • Utilice comillas. Evite que "blank" sea nothing.
  • La nueva notación moderna para las variables es ${variable}.
  • Agregar un cero concatenado antes de su número también evita «ningún número».
  • Pero espere, agregar un cero hace que el número se convierta en base-8. Obtendrá un error como:
    • value too great for base (error token is "08") para números superiores a 7. Es entonces cuando entra en juego 10#:
    • 10# fuerza que el número sea base-10.

Responder

Puede hacer esto:

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

Comentarios

  • Eso funciona pero es complicado. Si ‘ está ejecutando ping en una subcapa de una subcapa, la salida de ping se captura para ejecutarla como un comando. Pero debido a que la salida se redirige a / dev / null, esa siempre será la cadena vacía. Entonces, ‘ no está ejecutando nada en una subcapa, lo que significa que el estado de salida anterior (de la subcapa de sustitución de comandos, es decir, de ping) se mantendrá. Obviamente, la forma correcta es if ping ...; then aquí.

Responder

Como se señaló en otra parte de este hilo, la pregunta original básicamente se responde sola. Aquí hay una ilustración que muestra que las condiciones if también pueden estar anidadas.

Este ejemplo usa if para verificar si un archivo existe y si es un archivo normal. Si esas condiciones son verdaderas, verifique si tiene un tamaño mayor 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 

Comentarios

  • Eso es lo que hace su respuesta, pero su respuesta no aborda la pregunta.
  • @JeffSchaller, gracias por su nota. Edité mi publicación para incluir una referencia a la pregunta.

Respuesta

#!/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 

Comentarios

Respuesta

Esto se puede hacer simplemente de esta manera, ya que $? le da el estado del último comando ejecutado.

Entonces podría ser

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

Comentarios

  • Downvote: Esto simplemente parafrasea una respuesta anterior que ha recibido críticas legítimas por ser unidiomática.
  • En realidad, esto era exactamente lo que estaba buscando porque ‘ estoy intentando para hacer que el » comando » falle el script como parte de » set -e » que no ‘ t si es ‘ s parte del if.Esto no debería ‘ t ser votado en contra.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *