find(per i predicati -name/ -pathstandard) usa modelli jolly proprio come globs (nota che {a,b}non è un operatore glob; dopo l'espansione, ottieni due globs). La differenza principale è la gestione di barre (e file di punti e directory non trattati in modo speciale find). *nei globs non si estenderà su più directory. */*/*farà elencare fino a 2 livelli di directory. L'aggiunta di a -path './*/*/*'corrisponderà a tutti i file con almeno 3 livelli di profondità e non smetterà finddi elencare i contenuti di qualsiasi directory a qualsiasi profondità.
Per quel particolare
./foo*bar/quux[A-Z]{.bak,}/pic[0-9][0-9][0-9][0-9]?.jpg
un paio di globs, è facile da tradurre, stai cercando directory a profondità 3, quindi puoi usare:
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 {} +
(o -depth 3con alcune findimplementazioni). O 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 {} +
Il che garantirebbe che quelli *e ?non potrebbero abbinare i /personaggi.
( findcontrariamente a globs leggerebbe il contenuto di directory diverse da foo*barquelle presenti nella directory corrente¹, e non ordinerebbe l'elenco dei file. Ma se lasciamo da parte il problema che ciò che corrisponde [A-Z]o il comportamento di */ ?rispetto ai caratteri non validi è non specificato, otterrai lo stesso elenco di file).
Ma in ogni caso, come ha dimostrato @muru , non è necessario ricorrere findse si tratta solo di dividere l'elenco di file in più esecuzioni per aggirare il limite della execve()chiamata di sistema. Alcune shell come zsh(con zargs) o ksh93(con command -x) hanno persino il supporto integrato per questo.
Con zsh(i cui globs hanno anche l'equivalente -type fe la maggior parte degli altri findpredicati), ad esempio:
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)è un operatore glob contrario {,.bak}, il (.)qualificatore glob è l'equivalente di find's -type f, aggiungilo oNper saltare l'ordinamento come con find, Dper includere file dot (non si applica a questo glob))
¹ Per findeseguire la scansione dell'albero delle directory come farebbero globs, avresti bisogno di qualcosa del tipo:
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 \) \)
Cioè potare tutte le directory al livello 1 tranne foo*barquelle, e tutte al livello 2 tranne le quux[A-Z]o quux[A-Z].bak, quindi selezionare pic...quelle al livello 3 (e potare tutte le directory a quel livello).
-patho-ipath.find . -path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg'dovrebbe funzionare - tranne che corrisponderà/fooz/blah/bar/quuxA/pic1234d.jpg. Sarà un problema?