Различное поведение между find -exec и конвейеризацией через xargs

Различное поведение между find -exec и конвейеризацией через xargs

Я хотел рекурсивно запустить chmod go+wв определенной папке, включая скрытые файлы, и я сначала попробовал

find . -name ".*" -o -name "*" -exec chmod go+w {} \;

но я обнаружил, что это не влияет на скрытые файлы. Чтобы проверить себя, я запустил просто

find . -name ".*" -o -name "*"

и скрытые файлы были перечислены. Я также заметил, что если я исключил часть, -o -name "*"то это chmod для скрытых файлов (но исключало нескрытые, конечно). Моя последняя попытка была использовать xargs вместо

find . -name ".*" -o -name "*" | xargs chmod go+w

что наконец-то сработало как и ожидалось. Что я делаю не так в первом фрагменте?

Red Hat Enterprise Linux Server, выпуск 6.8 (Сантьяго)

GNU bash, версия 4.3.42(1)-релиз (x86_64-unknown-linux-gnu)

решение1

Решение состоит в том, чтобы связать два теста имени вместе с помощью скобок.

Чтобы проиллюстрировать это, давайте рассмотрим каталог с тремя обычными файлами:

$ ls -a
.  ..  .hidden1  .hidden2  not_hidden

Теперь давайте рассмотрим исходную команду:

$ find . -name ".*" -o -name "*" -exec echo Found {} \;
Found ./not_hidden

Найден только нескрытый файл.

Далее добавим скобки, чтобы сгруппировать два теста имени вместе:

$ find . \( -name ".*" -o -name "*" \) -exec echo Found {} \;
Found .
Found ./not_hidden
Found ./.hidden1
Found ./.hidden2

Все файлы найдены.

Решение — использовать скобки.

Подробнее

В исходной команде нет оператора между -name "*"и -exec ... \;. Следовательно, findпредполагается оператор по умолчанию, которым является логическое-и. Поскольку логическое-и связывает сильнее, чем логическое-или ( -o), это означает, что команда интерпретируется как:

find . \( -name ".*" \) -o \( -name "*" -exec echo Found {} \; \)

Это означает, что execзапускается только в том случае, если первое nameусловие не выполняется.

Для получения более подробной информации см.ОПЕРАТОРЫраздел в man find.

Что происходит без-exec

Давайте попробуем использовать простой пример -print:

$ find . -name ".*" -o -name "*" -print
./not_hidden

Как вы можете видеть, -printсвязано -name "*"с неявным логическим «и», как указано выше.

Но представьте, что происходит без указания каких-либо действий:

$ find . -name ".*" -o -name "*"
.
./not_hidden
./.hidden1
./.hidden2

Здесь все файлы были найдены. Причина в том, что в этой версии -oестьтолькооператор.

Связанный контент