find
(pour les prédicats -name
/ -path
standard) utilise des modèles génériques comme les globs (notez que ce {a,b}
n'est pas un opérateur glob; après expansion, vous obtenez deux globs). La principale différence réside dans la gestion des barres obliques (et des fichiers de points et des répertoires qui ne sont pas traités spécialement dans find
). *
dans globs ne s'étendra pas sur plusieurs répertoires. */*/*
entraînera la liste de 2 niveaux de répertoires. L'ajout d'un -path './*/*/*'
correspondra à tous les fichiers qui ont au moins 3 niveaux de profondeur et ne s'arrêtera pas find
de lister le contenu d'un répertoire à n'importe quelle profondeur.
Pour ce particulier
./foo*bar/quux[A-Z]{.bak,}/pic[0-9][0-9][0-9][0-9]?.jpg
quelques globes, c'est facile à traduire, vous voulez des répertoires en profondeur 3, donc vous pouvez utiliser:
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 {} +
(ou -depth 3
avec certaines find
implémentations). Ou POSIX:
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 {} +
Ce qui garantirait que ceux-ci *
et ?
ne pourraient pas correspondre aux /
caractères.
( find
, contrairement à globs lirait le contenu de répertoires autres que foo*bar
ceux du répertoire courant¹, et ne trierait pas la liste des fichiers. Mais si nous laissons de côté le problème de ce à quoi correspond [A-Z]
ou le comportement de *
/ ?
en ce qui concerne les caractères invalides non spécifié, vous obtiendrez la même liste de fichiers).
Mais dans tous les cas, comme l' a montré @muru , il n'est pas nécessaire d'y recourir find
s'il s'agit simplement de diviser la liste de fichiers en plusieurs exécutions pour contourner la limite de l' execve()
appel système. Certains shells comme zsh
(avec zargs
) ou ksh93
(avec command -x
) ont même un support intégré pour cela.
Avec zsh
(dont les globes ont également l'équivalent de -type f
et la plupart des autres find
prédicats), par exemple:
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)
est un opérateur glob contrairement à {,.bak}
, le (.)
qualificatif glob est l'équivalent de find
's' -type f
, ajoutez- oN
y pour ignorer le tri comme avec find
, D
pour inclure les fichiers de points (ne s'applique pas à ce glob))
¹ Pour find
explorer l'arborescence de répertoires comme le feraient les globes, vous auriez besoin de quelque chose comme:
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 \) \)
C'est-à-dire élaguer tous les répertoires au niveau 1 à l'exception de foo*bar
ceux et tous au niveau 2 à l'exception de ceux quux[A-Z]
ou quux[A-Z].bak
, puis sélectionner pic...
ceux au niveau 3 (et élaguer tous les répertoires à ce niveau).
-path
ou-ipath
.find . -path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg'
devrait fonctionner - sauf qu'il correspondra/fooz/blah/bar/quuxA/pic1234d.jpg
. Sera-ce un problème?