Мене збентежило те, чому надруковані каталоги також друкуються find
командою, і деякі інші складні деталі того, як -prune
працювали, але вдалося це зрозуміти за допомогою декількох прикладів.
Для запуску наведених нижче прикладів створіть наступні каталоги та файли.
mkdir aa
mkdir bb
touch file1
touch aa/file1
touch bb/file3
Щоб створити цю структуру:
$ tree
.
├── aa
│ └── file1
├── bb
│ └── file3
└── file1
Тепер використовуйте пошук для пошуку каталогів з назвою aa
. Тут немає жодних проблем.
$ find . -type d -name aa
./aa
Шукайте всі каталоги, крім aa, і ми отримуємо поточний каталог .
і ./bb
, що також має сенс.
$ find . -type d ! -name aa
.
./bb
Поки що добре, але коли ми використовуємо -prune
, знайде повертає каталог, який ми обрізаємо, що спочатку мене збентежило, тому що я очікував, що він поверне всі інші каталоги, а не той, який буде обрізаний.
$ find . -type d -name aa -prune
./aa
Причина, чому він повертає обрізаний каталог, пояснюється не в -prune
розділі довідкових сторінок, як зазначено у відповіді Тімо , а в EXPRESSIONS
розділі:
Якщо вираз не містить жодних інших дій, крім цього -prune
,
-print
виконується для всіх файлів, для яких вираз є істинним.
що означає, що оскільки вираз відповідає імені aa
каталогів, то вираз буде оцінено як істинне і воно буде надруковано, оскільки пошук неявно додає а -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
команду THE END в команду 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
працює. find
Сторінку " man" слід оновити, щоб уникнути невпевненої світової плутанини щодо цієї команди.
-print
, інакше неявне-print
стосується всієї умови