Як я зупиняю пошук, щоб не спускався до знайдених каталогів?


24

Я хочу знайти всі каталоги з певним рядком, щоб я міг ще раз знайти файли, що містяться в ньому.

Тому я не хочу витрачати час на ./my-search-term/dir/my-search-termтощо.

Як я можу припинити повторення, коли знайшов перший каталог мого пошуку?


3
Ви спробували знайти за допомогою -prune? Зі сторінки man: "якщо файл - це каталог, не спускайтеся в нього. Якщо -depth задано, false; немає ефекту. Оскільки -delete означає -depth, ви не можете корисно використовувати -prune та -delete разом."
в'язниця

1
@laebshade чому б ти не поставив це у відповідь?
jw013

@ jw013 На той час я не мав часу надати більш невмілу відповідь.
в'язниця

Відповіді:


17

-pruneДія робить findНЕ рекурсию в каталог. Ви можете комбінувати його з іншою дією, такою як -exec(порядок -pruneі -execне має значення, якщо -pruneвиконується в будь-якому випадку).

find . -name my-search-term -prune -exec find {} … \;

Зауважте, що гніздування findвсередині find -execможе бути трохи проблематичним: ви не можете використовувати -execвнутрішній find, оскільки термінатор буде розглядатися як термінатор зовнішнім find. Ви можете обійти це шляхом виклику оболонки, але остерігайтеся цитування.

find . -name my-search-term -prune -exec sh -c '
    find "$@" … -exec … {\} +
' _ {} +

Чи потрібні дужки у вашій першій команді? -pruneповертає істину і може бути поставлено перед -exec.
rozcietrzewiacz

@rozcietrzewiacz Ні, вони не потрібні. Звичка мати -oтам, я думаю. І я гадаю, що ставлення -pruneдо -execцього більш читабельне.
Жил "ТАК - перестань бути злим"

Дякую, раніше не використовували цю -pruneопцію.
haridsv

У моєму випадку використання цієї команди: mkdir -p x1 x2; touch x1/x11 x1/x12 x2/x21 x2/x22; find . -name 'x1*' -exec rm -rf {} \;видає помилку: find: ./x1: No such file or directory. Рішення - додати -pruneв кінці findкоманди.
haridsv

(1) Деякі версії findрозгортаються {}навіть тоді, коли це відображається як підрядка аргументу -exec. Така версія findбуде задушена вашою другою командою, оскільки {}внутрішня findкоманда (в команді shell) буде замінена на ім'я каталогу, знайденого у зовнішній find. Ви можете це виправити, сказавши, find . -name my-search-term -prune -exec sh -c 'find "$0" … -exec … "{"} +' {} \; тобто, використовуючи "{"}, в яку оболонка перетвориться {}. … (Продовження)
Скотт

6

- голі рішення -

Якщо ви хочете findпропустити вміст знайденого каталогу, але продовжувати пошук в інших каталогах, використовуйте -pruneяк запропоновано @laebshade. Потім повинна виглядати повна команда

 find . -type d -name somename -prune -exec ...

З іншого боку, якщо ви хочете , findщоб повністю припинити пошук і після знаходження першого каталогу відповідності, то , що ви шукаєте -quit(починаючи з версії 4.2.3про GNU find). Це трохи складніше у використанні, оскільки він робить findвихід негайно - тому його -quitпотрібно розмістити в самому кінці команди:

find . -type d -name somename -exec ... -quit

Щоб це працювало як очікувалося, треба переконатися, що -execповернення справжнє (іншими словами, нульовий статус). Якщо ви хочете -execігнорувати статус виходу , щоб це -quitзавжди працювало, вам потрібна невелика хитрість:

find . -type d -name somename \( -exec ... -o -true \) -quit

або

find . -type d -name somename \( -exec ... -o -quit \)

або

find . -type d -name somename \( -exec ... , -quit \) # a comma before -quit

- якесь пояснення -

Найголовніше, як findпрацює, - це те, що всі дії ("тести") трактуються як логічні предикати, інтерпретовані зліва направо. Тому остання дія (наприклад -quit) буде виконана лише в тому випадку, якщо вся попередня частина не повернула помилкового . За замовчуванням усі тести поєднуються з логічним "AND", -oопція змінює суглоб на "OR".

Складний елемент -o, який findможе "оптимізувати" вашу команду, а не запускати -execчастину, якщо ви просто введете

find . -type d -name somename -exec ... -o -quit

Щоб впоратися з цим, ви можете змусити findоцінити всі предикати, об'єднані з "АБО", додавши їх у круглі дужки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.