2008-11-26 8 views
34

Tanto acerca de las opciones "-E" en la documentación de Bash "-a" y (http://www.gnu.org/software/bash/manual/bashref.html#Bash-Conditional-Expressions):fiesta si se dice -a vs opción -e

-a file 
    True if file exists. 
-e file 
    True if file exists. 

Tratando de conseguir lo que la diferencia es que yo corría el siguiente secuencia de comandos:

resin_dir=/Test/Resin_wheleph/Results 

if [ -e ${resin_dir} ] ; then 
    echo "-e "; 
fi 

if [ ! -e ${resin_dir} ] ; then 
    echo "! -e"; 
fi 

if [ -a ${resin_dir} ] ; then 
    echo "-a"; 
fi 

if [ ! -a ${resin_dir} ] ; then 
    echo "! -a"; 
fi 

/Test/Resin_wheleph/Resultados existe y es un directorio. Y esto es lo que me pasa:

-e 
-a 
! -a 

que parece ser un poco extraño (aviso "-a" y "-a!"). Pero cuando se utiliza dobles corchetes (.. E g if [[ -e ${resin_dir} ]]) en la secuencia de comandos similares que da salida razonable:

-e 
-a 

Así:

  1. ¿Cuál es la diferencia entre "A" y opciones "-e"?
  2. ¿Por qué "-a" produce un resultado extraño cuando se utiliza dentro de corchetes individuales?
+0

no está seguro de si la página de manual está bien "hombre prueba" dice que es "y" –

Respuesta

48

he investigado, y esto es bastante peluda:

-a es obsoleto, por lo que no aparece en la página del manual de /usr/bin/test más, pero aún en el caso de bash. Use -e. Para el single '[', el bash builtin se comporta igual que el test bash builtin, que se comporta igual que /usr/bin/[ y /usr/bin/test (el uno es un enlace simbólico al otro). Tenga en cuenta que el efecto de -a depende de su posición: si está al principio, significa file exists. Si está en el medio de dos expresiones, significa que es lógico and.

[ ! -a /path ] && echo exists no funciona, como el manual de golpe señala que -a se considera un operador binario allí, y por lo que la anterior no se analiza como un negate -a .. sino como un if '!' and '/path' is true (no vacía). Por lo tanto, su script siempre muestra "-a" (que en realidad prueba los archivos), y "! -a" que en realidad es un and binario aquí.

Para [[, -a no se utiliza como un binario and más (&& se utiliza allí), por lo que su única finalidad es comprobar que un archivo existe (aunque se use). Entonces, la negación realmente hace lo que esperas.

+0

la orden interna bash usa -a -e como en el modo unario y -a como AND en modo binario. Usar [[]] invoca el bashs incorporado, es por eso que tiene un resultado razonable con él. El corchete simple invoca como se menciona el binario de prueba que acepta el unario pero no lo trata bien (debe usarse como binario) – flolo

+1

Muy pocas conchas realmente invocan/b in/test (o/bin/[) cuando escribe 'if [...]'. Una vez hace mucho tiempo, sí; hoy en día, no. Ni siquiera vainilla Bourne shell. –

+0

Sí, creo que los shell builtins siempre tienen prioridad –

0

El doble corchete [[exp]] es un bash incorporado. En bash -a y -e son lo mismo, probablemente para cierta compatibilidad con versiones anteriores.

El paréntesis único [exp] es un alias para el comando externo "prueba". En "prueba", -a es un AND lógico. Aunque [nada AND $ STRING] parece que debería ser falso, la prueba tiene algunas peculiaridades de sintaxis, por lo que recomiendo usar bash builtin [[exp]], que tiende a ser más sensato.

Nota: bash realmente llama/bin/[cuando usa "[".

$ [ $UNASIGNED_VAR == "bar" ] 
bash: [: ==: unary operator expected 

error muestra bash llamado [. Una strace también muestra "execve ("/usr/bin/[", ..."

+0

[js @ HOST2 cpp] $ alias foo bash: alias: foo: no encontrado [js @ HOST2 cpp] $ significa eso alias ahora es un comando externo? no, sigue siendo un builtin :) –

+0

maldito, bueno :). Aún así, strace'ing a bash script revela "execve ("/usr/bin/[", ... – JimB

+0

Interesante: en Solaris, usando 'truss -o bash.truss bash ...' como en mi respuesta y luego usar 'grep -n exec bash.truss' muestra solo la línea 1 ejecutando bash en sí mismo. Eso es bastante extraño. (Tampoco hay/usr/bin/[en Solaris - hay una/usr/bin/test.) –

3

La opción '-a' para el operador de prueba tiene un significado como operador unario y otro como operador binario. Como operador binario, es el conector 'y' (y '-o' es el 'o' Conective). Como operador unario, aparentemente prueba la existencia de un archivo.

El sistema autoconf le aconseja evitar el uso de '-a' porque causa confusión; ahora veo por qué. De hecho, en la programación de shell portátil, es mejor combinar las condiciones con '&&' o '||'.

Creo que @litb está a la derecha seguimiento. Cuando tiene '! -a ${resin_dir}', ¡Bash puede interpretarlo como "es la cadena '!' no está vacío y la cadena en '$ {resina_dir}' no está vacía, a lo que la respuesta es sí. El shell Korn tiene una vista diferente sobre esto, y el shell Bourne otra vista, así que mantente alejado de '-a' .

en Solaris 10:.

$ bash -c 'x=""; if [ ! -a "$x" ] ; then echo OK ; else echo Bad; fi' 
Bad 
$ ksh -c 'x=""; if [ ! -a "$x" ] ; then echo OK ; else echo Bad; fi' 
OK 
$ sh -c 'x=""; if [ ! -a "$x" ] ; then echo OK ; else echo Bad; fi' 
sh: test: argument expected 
$ 
Cuestiones relacionadas