Я хотел рекурсивно запустить 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
естьтолькооператор.