find(для предикатов -name/ -pathstandard) используются шаблоны с подстановочными знаками, аналогично globs (обратите внимание, что {a,b}это не оператор glob; после расширения вы получите два glob). Основным отличием является обработка слешей (и файлов с точками и директорий, которые не обрабатываются специально find). *в шарах не будет охватывать несколько каталогов. */*/*приведет к перечислению до 2 уровней каталогов. Добавление -path './*/*/*'будет соответствовать любым файлам глубиной не менее 3-х уровней и не остановит 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реализациями). Или положительно:
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отличие от globs прочитал бы содержимое каталогов, отличных 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)оператор glob противоречит {,.bak}, (.)квалификатор glob является эквивалентом find's' -type f, добавьте oNтуда, чтобы пропустить сортировку, например find, Dс включением точек-файлов (не относится к этому глобу))
¹ Для того, 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. Это будет проблемой?