Как я могу остановить поиск находок в найденных каталогах?


24

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

Поэтому я не хочу тратить время ./my-search-term/dir/my-search-termи т. Д.

Как я могу прекратить повторение, когда я нашел первый каталог my-search-term?


3
Вы пытались найти с -prune? Со страницы руководства: «если файл является каталогом, не спускайтесь в него. Если задано -depth, ложно; эффекта нет. Поскольку -delete подразумевает -depth, вы не можете использовать вместе -prune и -delete вместе».
laebshade

1
@laebshade, почему бы тебе не добавить это в ответ?
jw013

@ jw013 В то время у меня не было времени дать более глубокий ответ.
laebshade

Ответы:


17

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

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

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

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

Нужны ли скобки в вашей первой команде? -pruneвозвращает true и может быть поставлено перед -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команде (в команде оболочки) будет заменена именем директории, найденной во внешней find. Вы можете это исправить, сказав find . -name my-search-term -prune -exec sh -c 'find "$0" … -exec … "{"} +' {} \; ie, используя "{"}, во что превратится оболочка {}. … (Продолжение)
Скотт

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возвращается true (другими словами, нулевой статус). Если вы хотите, чтобы статус выхода -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) будет выполнено только в том случае, если вся предыдущая часть не вернула false . По умолчанию все тесты объединяются с логическим «И», -oопция меняет соединение на «ИЛИ».

Хитрый элемент в -oтом, что findможет "оптимизировать" вашу команду и не запускать -execчасть, если вы просто наберете

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

Чтобы справиться с этим, вы можете принудительно findоценить все предикаты, обозначенные «ИЛИ», заключив их в круглые скобки.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.