find(для -name/ -pathстандартних предикатів) використовує шаблони підстановок так само, як глобуси (зверніть увагу, що {a,b}це не глобальний оператор; після розширення ви отримуєте два глобуси). Основна відмінність - поводження з косою рисою (а також крапки з файлами та брудом, за якими спеціально не обробляються find). *в глобусах не буде охоплено декілька каталогів. */*/*призведе до переліку до двох рівнів каталогів. Додавання -path './*/*/*'відповідатиме будь-яким файлам, що мають глибину щонайменше трьох рівнів, і не зупинятиметься findперелічувати вміст будь-якого каталогу на будь-якій глибині.
Для конкретного
./foo*bar/quux[A-Z]{.bak,}/pic[0-9][0-9][0-9][0-9]?.jpg
кілька глобусів, це легко перекласти, ви хочете мати каталоги на глибині 3, щоб ви могли використовувати:
find . -mindepth 3 -maxdepth 3 \
\( -path './foo*bar/quux[A-Z].bak/pic[0-9][0-9][0-9][0-9]?.jpg' -o \
-path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg' \) \
-exec cmd {} +
(або -depth 3з деякими findреалізаціями). Або POSIXly:
find . -path './*/*/*' -prune \
\( -path './foo*bar/quux[A-Z].bak/pic[0-9][0-9][0-9][0-9]?.jpg' -o \
-path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg' \) \
-exec cmd {} +
Що гарантувало б, що ті *і ?не могли відповідати /персонажам.
( findвсупереч глобусам буде читати вміст каталогів, відмінних від foo*barпоточного в каталозі¹, а не сортувати список файлів. Але якщо ми залишимо осторонь, що те, що відповідає [A-Z]або поведінка */ ?щодо недійсних символів, - це не вказано, ви отримаєте той самий список файлів).
Але в будь-якому випадку, як показало @muru , не потрібно вдаватися, findякщо це лише для розбиття списку файлів на кілька запусків, щоб обійти межу execve()системного виклику. Деякі оболонки типу zsh(з zargs) або ksh93(з command -x) навіть мають вбудовану підтримку для цього.
З zsh(чиї кульками також мають еквівалент -type fі більшість інших findпредикатів), наприклад:
autoload zargs # if not already in ~/.zshrc
zargs ./foo*bar/quux[A-Z](|.bak)/pic[0-9][0-9][0-9][0-9]?.jpg(.) -- cmd
( (|.bak)Є оператором Глоб всупереч {,.bak}, то (.)Глоб класифікатор є еквівалентом find«s -type f, додайте oNтуди , щоб пропустити сортування , як з find, Dщоб включити дот-файли (не відноситься до цього Glob))
¹ Щоб findсканувати дерево каталогів, як глобуси, вам знадобиться щось на зразок:
find . ! -name . \( \
\( -path './*/*' -o -name 'foo*bar' -o -prune \) \
-path './*/*/*' -prune -name 'pic[0-9][0-9][0-9][0-9]?.jpg' -exec cmd {} + -o \
\( ! -path './*/*' -o -name 'quux[A-Z]' -o -name 'quux[A-Z].bak' -o -prune \) \)
Тобто обрізайте всі каталоги на рівні 1, крім foo*barтих, і всі на рівні 2, окрім quux[A-Z]або quux[A-Z].bak, та виберіть pic...їх на рівні 3 (та обріжте всі каталоги на цьому рівні).
-pathабо-ipath.find . -path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg'повинен працювати - крім того, що це буде відповідати/fooz/blah/bar/quuxA/pic1234d.jpg. Це буде проблема?