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?

atxdba
fuente

Respuestas:

532
if [ ! -z "$var" ] && [ -e "$var" ]; then
      # something ...
fi
jaypal singh
fuente
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
paxdiablo
fuente
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

 

Slava Semushin
fuente
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)

usuario123444555621
fuente
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 ...

rororo
fuente