
У меня возникли проблемы с расшифровкой страницы руководства find, особенно той части, где указан порядок оценки логических операторов, связывающих тесты. На странице руководства говорится:
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.
Пока все хорошо: я составил две программы:
#include <stdio.h>
int main (int argc, char **argv) {
printf("THIS IS PGM1. I RETURN FALSE.\n");
return 1;
}
и
#include <stdio.h>
int main (int argc, char **argv) {
printf("THIS IS PGM2. I RETURN TRUE.\n");
return 0;
}
Тогда у меня есть:
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$
Мне кажется, что способ, которым find оценивает логические операторы, отличается от описания на странице руководства. Он идет слева направо, -o
и и -a
имеют одинаковый приоритет. Я что-то упускаю?
решение1
Ваш тест не демонстрирует различий в приоритетах; попробуйте
find . -exec ./pgm1 \; -print -o -exec ./pgm2 \;
чтобы увидеть разницу. -a
(или отсутствие оператора) связывает сильнее, чем -o
, поэтому -print
связан с -exec ./pgm1
и никогда не оценивается, поскольку pgm1
всегда терпит неудачу.
В вашем примере для каждого найденного файла find
запускается pgm1
, что завершается неудачей, заставляя find
оценить другую ветвь оператора -o
, поэтому запускается pgm2
, что завершается успешно, а затем -print
.
решение2
find . -exec ./pgm1 \; -o -exec ./pgm2 \; -print
|---expr1-----| |----expr2------------|
Код выхода pgm1
всегда1, что означает, что expr1 ложно. Согласно странице руководства find
будет оценивать expr2, что pgm2
в данном случае.
Так что оба pgm1
были pgm2
казнены.
решение3
Подведем итоги еще раз, чтобы увидеть, правильно ли я понял на этот раз: find всегда оценивает предикаты таким образом, что разделяет командную строку на две части — «левую» и «правую». Когда он решает, как ее разделить, приоритет операторов берет на себя управление, и строка разделяется по оператору с наименьшим приоритетом. Затем сначала выполняется левая часть, а затем, в конечном итоге, правая часть. И если каждая часть имеет более двух предикатов, объединенных логическим оператором, она выполняется рекурсивно тем же способом.
решение4
Таким образом, по сути, более высокий приоритет -and не означает, что он будет выполнен первым, а означает, что он будет выполнен последним... То есть «-a связывает больше, чем -o».