Bash condicionales: ¿cómo “y” expresiones? (si [! -z $ VAR && -e $ VAR])


281

Supongo que no tengo claro cómo hacer "y" pruebas. Quería asegurarme de que existiera un argumento que funcionara bien [ -e $VAR ], pero resulta que también se estaba evaluando como verdadero en una cadena vacía; que no quiero

¿Cómo los 'y' juntos? ¿O hay otra prueba unaria que logra lo que quiero?

Respuestas:


532
if [ ! -z "$var" ] && [ -e "$var" ]; then
      # something ...
fi

9
Esta solución funciona incluso en shells estrictamente compatibles con POSIX y, por lo tanto, también en bash; sin embargo, para aprovechar al máximo los "bashismos", vea la respuesta de @ paxdiablo.
— mklement0

2
Muy contento de ver esto aconsejado en lugar de lo obsoleto -a.
— Charles Duffy

1
He encontrado otra excelente y detallada explicación - stackoverflow.com/questions/3601515/...
— valentt

70

Desde la página del bashmanual:

[[ expression ]] - devuelve un estado de 0 o 1 dependiendo de la evaluación de la expresión de expresión condicional.

Y, para las expresiones, una de las opciones es:

expression1 && expression2- cierto si ambos expression1y expression2son verdaderos.

Entonces puedes andjuntarlos de la siguiente manera ( -nes lo contrario de -zpara que podamos deshacernos de !):

if [[ -n "$var" && -e "$var" ]] ; then
    echo "'$var' is non-empty and the file exists"
fi

Sin embargo, no creo que sea necesario en este caso, -e xyzzyes cierto si el xyzzy archivo existe y puede manejar fácilmente cadenas vacías. Si eso es lo que quieres, entonces no necesitas el -zcheque no vacío:

pax> VAR=xyzzy
pax> if [[ -e $VAR ]] ; then echo yes ; fi
pax> VAR=/tmp
pax> if [[ -e $VAR ]] ; then echo yes ; fi
yes

En otras palabras, solo use:

if [[ -e "$var" ]] ; then
    echo "'$var' exists"
fi

1
Podemos acortarlo con[[ -e "$var" ]] && echo "'$var' exists"
— jaypal singh

1
Sí, si es de una sola línea (como fue mi ejemplo). Sin embargo, no haría eso si el bloque condicional fuera mucho más complejo.
— paxdiablo

en caso de que solo haya un comando, quizás incluso uno largo, tiene sentido usar este formulario ya que es más corto
— avp

9
if [ -n "$var" -a -e "$var" ]; then
    do something ...
fi

 


10
Como POSIXno define el comportamiento de [con conjuntos complejos de pruebas, debemos evitar usar -ao -ocon [. Lo leí aquí .
— jaypal singh

2
@ jaypal-singh Tienes razón, pero el tema tiene bashetiqueta y no menciona sobre POSIX, así que publico esta versión que funciona bajo bashy algunos otros shells modernos.
— Slava Semushin

2
Si está asumiendo el uso de bashu otros proyectiles modernos, hay incluso menos razones para recomendarlo -a.
— chepner

Incluso con bash, la forma en que se comportan estas pruebas no está bien definida en todos los casos de esquina. Considerar [ "$var1" -o "$var2" ]; si var1=(y var2=), entonces lo que tenemos es una prueba de si -ono está vacío, en lugar de si está var1o var2no está vacío. Este tipo de ambigüedad es la única razón legítima para el x$varmodismo en los testcomandos modernos (es decir, posteriores a los 90) con una cita correcta, y ese modismo debe morir en un incendio.
— Charles Duffy

4

Simplemente cita tu variable:

[ -e "$VAR" ]

Esto evalúa [ -e "" ]si $VARestá vacío.

Su versión no funciona porque se evalúa como [ -e ]. Ahora, en este caso, bash simplemente comprueba si el argumento único ( -e) es una cadena no vacía.

Desde la página del manual:

prueba y [evalúa expresiones condicionales usando un conjunto de reglas basadas en el número de argumentos. ...

1 argumento

La expresión es verdadera si y solo si el argumento no es nulo.

(Además, esta solución tiene la ventaja adicional de trabajar con nombres de archivo que contienen espacios)


1

Encontré una respuesta ahora. Gracias por tus sugerencias!

for e in ./*.cutoff.txt; do
if grep -q -E 'COX1|Cu-oxidase' $e
then
    echo xyz >$e.match.txt
else
    echo
fi

if grep -q -E 'AMO' $e
then
    echo abc >$e.match.txt
else
    echo
fi; done

¿Algún comentario sobre eso? Parece ineficiente hacer grep dos veces, pero funciona ...

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.