Я был озадачен тем, почему findкоманда также печатала обрезанные каталоги , и некоторыми другими запутанными подробностями того, как это -pruneработает, но смог выяснить это на нескольких примерах.
Для запуска приведенных ниже примеров создайте следующие каталоги и файлы.
mkdir aa
mkdir bb
touch file1
touch aa/file1
touch bb/file3
Чтобы создать эту структуру:
$ tree
.
├── aa
│ └── file1
├── bb
│ └── file3
└── file1
Теперь используйте find для поиска каталогов с именем aa. Здесь нет проблем.
$ find . -type d -name aa
./aa
Ищите все каталоги, кроме aa, и мы получим текущий каталог .и ./bb, что также имеет смысл.
$ find . -type d ! -name aa
.
./bb
Пока все хорошо, но когда мы используем -prune, find возвращает каталог, который мы удаляем, что поначалу меня смутило, потому что я ожидал, что он вернет все остальные каталоги, а не тот, который был удален.
$ find . -type d -name aa -prune
./aa
Причина, по которой он возвращает удаляемый каталог, объясняется не в -pruneразделе справочных страниц, как указано в ответе Тимо , а в EXPRESSIONSразделе:
Если выражение не содержит никаких действий, кроме -prune,
-printвыполняется для всех файлов, для которых выражение является истинным.
Это означает, что, поскольку выражение совпадает с aaименем каталога, выражение будет иметь значение true и будет напечатано, потому что find неявно добавляет a -printв конце всей команды. Однако это не добавит -print, если вы намеренно добавили действие -o -printв конец самостоятельно:
find . -type d -name aa -prune -o -print
.
./file1
./bb
./bb/file3
Здесь команда find больше НЕ добавляет неявное -print, и поэтому каталог, который мы отбрасываем ( aa), не будет напечатан.
Итак, наконец, если мы добавим предложение, которое ищет файлы с шаблоном имени файла file*после -o, то вы должны поставить -printв конце этого второго предложения, как это:
find . \( -type d -name aa -prune \) -o \( -type f -name 'file*' -print \)
./file1
./bb/file3
Причина, по которой это работает, одна и та же: если вы не поместите a -printво второе предложение, то, поскольку нет действия, кроме -pruneдействия, find автоматически добавит -printв конце команды END, в результате чего -pruneпредложение напечатает подрезанный каталог:
find . \( \( -type d -name aa -prune \) -o \( -type f -name 'file*' \) \) -print
./aa
./file1
./bb/file3
В общем, вам нужно поместить -printкоманду во втором предложении. Если вы поместите его посередине, как это делал оригинальный постер, он не будет работать правильно, потому что удаляемые файлы будут распечатаны немедленно, а во втором предложении не будет возможности выбрать нужные файлы:
find . \( -type d -name aa -prune -o -print \) -o \( -type f -name 'file*' \)
.
./file1
./bb
./bb/file3
Так что, к сожалению, оригинальный постер неправильно дал команду выше, поместив ее -printв неправильном месте. Это могло бы сработать для его конкретного случая, но в общем случае это не сработало.
Есть тысячи людей, которым трудно понять, как -pruneработает. Страница findman должна быть обновлена, чтобы предотвратить бесконечную путаницу во всем мире по поводу этой команды.
-print, иначе неявное-printотносится ко всему условию