J'ai remarqué récemment que les spécifications POSIX pourfind
ne comprennent pas le -maxdepth
primaire.
Pour ceux qui ne le connaissent pas, l'objectif du -maxdepth
primaire est de limiter le nombre de niveaux profonds find
qui descendront. -maxdepth 0
entraîne uniquement le traitement des arguments de ligne de commande; -maxdepth 1
ne traiterait que les résultats directement dans les arguments de ligne de commande, etc.
Comment puis-je obtenir le comportement équivalent au -maxdepth
primaire non-POSIX en utilisant uniquement les options et outils spécifiés par POSIX?
(Remarque: bien sûr, je peux obtenir l'équivalent de -maxdepth 0
simplement en utilisant -prune
comme premier opérande, mais cela ne s'étend pas à d'autres profondeurs.)
-depth -2
,-depth 1
... l'approche pourrait être considérée comme meilleure que celle de GNU-maxdepth
/-mindepth
-maxdepth
/-mindepth
, il existe des alternatives raisonnables (notez qu'il-path
s'agit d'un ajout récent à POSIX). Les alternatives pour-timexy
ou-mtime -3m
(ou-mmin -3
) sont beaucoup plus lourdes. Certains aiment-execdir
/-delete
n'ont pas d'alternative fiable.Réponses:
Vous pouvez utiliser
-path
pour faire correspondre une profondeur donnée et y tailler. Par exempleserait maxdepth 1, car
*
correspond à.
,*/*
correspond à./dir1
et*/*/*
correspond à l'./dir1/dir2
élagage. Si vous utilisez un répertoire de départ absolu, vous devez également ajouter un début/
au-path
.la source
/*
la fin du motif, retirer l'-o
opérateur et obtenir le même résultat?*
correspondances/
aussi, donc le dira/b/c/d/e
conviendrait-path */*
, malheureusement.a/b/c/d/e
ne serait jamais atteint , car-prune
serait appliqué àa/b
....-prune
et j'ai-o
été supprimé. Si vous gardez le-prune
problème, c'est que le*/*
ne correspondra à rien à un niveau supérieur à maxdepth, par exemple le répertoire uniquea
.L'approche de @ meuh est inefficace car son
-maxdepth 1
approche permet toujours defind
lire le contenu des répertoires au niveau 1 pour les ignorer ultérieurement autrement. Il ne fonctionnera pas non plus correctement avec certainesfind
implémentations (y compris GNUfind
) si certains noms de répertoire contiennent des séquences d'octets qui ne forment pas de caractères valides dans les paramètres régionaux de l'utilisateur (comme pour les noms de fichiers dans un codage de caractères différent).est la manière la plus canonique d'implémenter GNU
-maxdepth 1
(ou FreeBSD-depth -2
).En règle générale, c'est que
-depth 1
vous voulez (-mindepth 1 -maxdepth 1
) que vous ne voulez pas considérer.
(profondeur 0), et c'est encore plus simple:Car
-maxdepth 2
cela devient:Et c'est là que vous rencontrez les problèmes de caractères non valides.
Par exemple, si vous avez un répertoire appelé
Stéphane
mais quié
est encodé dans le jeu de caractères iso8859-1 (aka latin1) (0xe9 octet) comme c'était le plus courant en Europe occidentale et en Amérique jusqu'au milieu des années 2000, alors cet octet 0xe9 n'est pas un caractère valide en UTF-8. Ainsi, dans les paramètres régionaux UTF-8, le*
caractère générique (avec certainesfind
implémentations) ne correspondra pasStéphane
tel quel*
ou plusieurs caractères et 0xe9 n'est pas un caractère.Mon
find
(lorsque la sortie est envoyée à un terminal) affiche cet octet 0xe9 non valide comme?
ci-dessus. Vous pouvez voir que ceSt<0xe9>phane/Chazelas
n'était pasprune
d.Vous pouvez contourner ce problème en faisant:
Mais notez que cela affecte tous les paramètres régionaux
find
et toutes les applications qu'il exécute (comme via les-exec
prédicats).Maintenant, je reçois vraiment un
-maxdepth 2
mais notez comment le é du second Stéphane correctement codé en UTF-8 est affiché comme??
les octets 0xc3 0xa9 (considérés comme deux caractères individuels non définis dans les paramètres régionaux C) du codage UTF-8 de é sont caractères non imprimables dans les paramètres régionaux C.Et si j'avais ajouté un
-name '????????'
, j'aurais eu le mauvais Stéphane (celui encodé en iso8859-1).Pour appliquer à des chemins arbitraires au lieu de
.
, vous feriez:pour
-mindepth 1 -maxdepth 1
ou:pour
-maxdepth 2
.Je ferais quand même:
D'abord parce que cela raccourcit les chemins, ce qui le rend moins susceptible de rencontrer des problèmes de chemin trop longs ou de liste d'arguments trop longs , mais aussi de contourner le fait qu'il
find
ne peut pas prendre en charge les arguments de chemin arbitraires (sauf-f
avec FreeBSDfind
) car il s'étouffera valeurs$dir
similaires!
ou-print
...La
-o
combinaison avec la négation est une astuce courante pour exécuter deux ensembles indépendants de-condition
/-action
infind
.Si vous souhaitez exécuter une
-action1
réunion de fichiers-condition1
et indépendamment une-action2
réunion de fichiers-condition2
, vous ne pouvez pas:Comme
-action2
ne serait exécuté que pour les fichiers répondant aux deux conditions.Ni:
Comme
-action2
ne serait pas exécuté pour les fichiers qui remplissent les deux conditions.fonctionne comme
\( ! -condition1 -o -action1 \)
résoudrait true pour chaque fichier. Cela suppose que-action1
c'est une action (comme-prune
,-exec ... {} +
) qui retourne toujours vrai . Pour des actions comme-exec ... \;
celle-ci peuvent retourner faux , vous voudrez peut-être ajouter un autre-o -something
où-something
est inoffensif mais renvoie vrai comme-true
dans GNUfind
ou-links +0
ou-name '*'
(bien que notez le problème des caractères invalides ci-dessus).la source
J'ai rencontré un problème où j'avais besoin d'un moyen de limiter la profondeur lors de la recherche sur plusieurs chemins (au lieu de simplement
.
).Par exemple:
Cela m'a conduit à une approche alternative utilisant -regex. L'essentiel est:
Donc, ce qui précède serait:
Sans nom de fichier:
Enfin, pour
-maxdepth 2
le regex, il devient:'(dir1|dir2)/([^/]*/){0,1}[^/]*$'
la source
-maxdepth
avec plusieurs chemins de recherche.