L'approche de @ meuh est inefficace car son -maxdepth 1approche permet toujours de findlire le contenu des répertoires au niveau 1 pour les ignorer ultérieurement autrement. Il ne fonctionnera pas non plus correctement avec certaines findimplémentations (y compris GNU find) 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).
find . \( -name . -o -prune \) -extra-conditions-and-actions
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 1vous voulez ( -mindepth 1 -maxdepth 1) que vous ne voulez pas considérer .(profondeur 0), et c'est encore plus simple:
find . ! -name . -prune -extra-conditions-and-actions
Car -maxdepth 2cela devient:
find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
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éphanemais 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 certaines findimplémentations) ne correspondra pas Stéphanetel quel *ou plusieurs caractères et 0xe9 n'est pas un caractère.
$ locale charmap
UTF-8
$ find . -maxdepth 2
.
./St?phane
./St?phane/Chazelas
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
$ find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St?phane/Chazelas/age
./St?phane/Chazelas/gender
./St?phane/Chazelas/address
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
Mon find(lorsque la sortie est envoyée à un terminal) affiche cet octet 0xe9 non valide comme ?ci-dessus. Vous pouvez voir que ce St<0xe9>phane/Chazelasn'était pas pruned.
Vous pouvez contourner ce problème en faisant:
LC_ALL=C find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
Mais notez que cela affecte tous les paramètres régionaux findet toutes les applications qu'il exécute (comme via les -execprédicats).
$ LC_ALL=C find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St??phane
./St??phane/Chazelas
./John
./John/Smith
Maintenant, je reçois vraiment un -maxdepth 2mais 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:
find some/dir/. ! -name . -prune ...
pour -mindepth 1 -maxdepth 1ou:
find some/dir/. \( ! -path '*/./*/*' -o -prune \) ...
pour -maxdepth 2.
Je ferais quand même:
(cd -P -- "$dir" && find . ...)
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 findne peut pas prendre en charge les arguments de chemin arbitraires (sauf -favec FreeBSD find) car il s'étouffera valeurs $dirsimilaires !ou -print...
La -ocombinaison avec la négation est une astuce courante pour exécuter deux ensembles indépendants de -condition/ -actionin find.
Si vous souhaitez exécuter une -action1réunion de fichiers -condition1et indépendamment une -action2réunion de fichiers -condition2, vous ne pouvez pas:
find . -condition1 -action1 -condition2 -action2
Comme -action2ne serait exécuté que pour les fichiers répondant aux deux conditions.
Ni:
find . -contition1 -action1 -o -condition2 -action2
Comme -action2ne serait pas exécuté pour les fichiers qui remplissent les deux conditions.
find . \( ! -condition1 -o -action1 \) -condition2 -action2
fonctionne comme \( ! -condition1 -o -action1 \)résoudrait true pour chaque fichier. Cela suppose que -action1c'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 -somethingoù -somethingest inoffensif mais renvoie vrai comme -truedans GNUfind ou -links +0ou -name '*'(bien que notez le problème des caractères invalides ci-dessus).
-depth -2,-depth 1... l'approche pourrait être considérée comme meilleure que celle de GNU-maxdepth/-mindepth