
Tengo problemas para descifrar la página del manual de find y sobre todo la parte que indica el orden de evaluación de los operadores lógicos que vinculan las pruebas. La página de manual dice:
OPERATORS
Listed in order of decreasing precedence:
( expr )
Force precedence. Since parentheses are special to the shell,
you will normally need to quote them.
Many of the examples in this manual page use backslashes
for this purpose: `\(...\)' instead of `(...)'.
expr1 expr2
Two expressions in a row are taken to be joined with an
implied -a; expr2 is not evaluated if expr1 is false.
expr1 -a expr2
Same as expr1 expr2.
expr1 -o expr2
Or; expr2 is not evaluated if expr1 is true.
Please note that -a when specified implicitly (for example by two
tests appearing without an explicit operator between them) or
explicitly has higher precedence than -o. This means that
find . -name afile -o -name bfile -print will never print afile.
Hasta ahora todo bien: he compilado dos programas:
#include <stdio.h>
int main (int argc, char **argv) {
printf("THIS IS PGM1. I RETURN FALSE.\n");
return 1;
}
y
#include <stdio.h>
int main (int argc, char **argv) {
printf("THIS IS PGM2. I RETURN TRUE.\n");
return 0;
}
Luego tengo:
lalev@dragonfly:~/example10$ ls -l
total 32
-rwxrwxr-x 1 lalev lalev 8296 Jan 18 12:16 pgm1
-rw-rw-r-- 1 lalev lalev 112 Jan 18 12:16 pgm1.c
-rwxrwxr-x 1 lalev lalev 8296 Jan 18 12:16 pgm2
-rw-rw-r-- 1 lalev lalev 111 Jan 18 12:16 pgm2.c
-rw-rw-r-- 1 lalev lalev 0 Jan 17 23:10 test1
lalev@dragonfly:~/example10$ find . -exec ./pgm1 \; -o -exec ./pgm2 \; -print
THIS IS PGM1. I RETURN FALSE.
THIS IS PGM2. I RETURN TRUE.
.
THIS IS PGM1. I RETURN FALSE.
THIS IS PGM2. I RETURN TRUE.
./pgm1.c
[...]
lalev@dragonfly:~/example10$
Me parece que la forma en que find evalúa los operadores lógicos difiere de la descripción en la página de manual. Va de izquierda a derecha -o
y -a
tiene la misma prioridad. ¿Me estoy perdiendo de algo?
Respuesta1
Su prueba no demuestra diferencias de precedencia; intentar
find . -exec ./pgm1 \; -print -o -exec ./pgm2 \;
para ver la diferencia. -a
(o ningún operador) se vincula con más fuerza que -o
, por lo que -print
está vinculado -exec ./pgm1
y nunca se evalúa ya que pgm1
siempre falla.
En su ejemplo, para cada archivo que encuentra, find
ejecuta pgm1
, lo cual falla, lo que hace find
que se evalúe la otra rama del -o
operador, por lo que ejecuta pgm2
, que tiene éxito, seguido de -print
.
Respuesta2
find . -exec ./pgm1 \; -o -exec ./pgm2 \; -print
|---expr1-----| |----expr2------------|
El código de salida de pgm1
es siempre1, lo que significa que expr1 es falso. Según la página del manual find
se evaluará expr2, que es pgm2
en este caso.
Así que ambos pgm1
fueron pgm2
ejecutados.
Respuesta3
Para resumir una vez más para ver si lo entendí esta vez: find siempre evalúa los predicados de tal manera que divide la línea de comando en dos: la parte "izquierda" y la "derecha". Cuando decide cómo dividirla, el operador con prioridad toma el control y la línea se divide por el operador con menor prioridad. Luego se ejecuta primero la parte izquierda y finalmente, la parte derecha. Y si cada parte tiene más de dos predicados, unidos por un operador lógico, se ejecuta recursivamente de la misma manera.
Respuesta4
Entonces, básicamente la precedencia más alta de -and no significa que se ejecuta primero, sino que se ejecuta al final... Es decir, "-a vincula más que -o".