TL; DR: la meilleure façon est d'utiliser à la -exec rmplace de -delete.
find a \( -name b -prune \) -o -type f -exec rm {} +
Explication:
Pourquoi find se plaint-il lorsque vous essayez d'utiliser -deleteavec -prune?
Réponse courte: car -deleteimplique -depthet -depthrend -pruneinefficace.
Avant d'arriver à la réponse longue, observons d'abord le comportement de la recherche avec et sans -depth:
$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2
Il n'y a aucune garantie sur la commande dans un seul répertoire. Mais il y a une garantie qu'un répertoire est traité avant son contenu. Notez foo/avant tout foo/*et foo/baravant tout foo/bar/*.
Cela peut être inversé avec -depth.
$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/
Notez que maintenant tous foo/*apparaissent avant foo/. Même chose avec foo/bar.
Réponse plus longue:
-pruneempêche la recherche de descendre dans un répertoire. En d'autres termes, -prunesaute le contenu du répertoire. Dans votre cas, -name b -pruneempêche la recherche de descendre dans n'importe quel répertoire portant le nom b.
-depthfait rechercher pour traiter le contenu d'un répertoire avant le répertoire lui-même. Cela signifie qu'au moment où find parvient à traiter l'entrée de répertoire, bson contenu a déjà été traité. Ainsi -pruneest inefficace avec -depthen vigueur.
-deleteimplique -depthqu'il peut d'abord supprimer les fichiers, puis le répertoire vide. -deleterefuse de supprimer les répertoires non vides. Je suppose qu'il serait possible d'ajouter une option pour forcer -deleteà supprimer les répertoires non vides et / ou empêcher -deleted'impliquer -depth. Mais c'est une autre histoire.
Il existe une autre façon de réaliser ce que vous voulez:
find a -not -path "*/b*" -type f -delete
Cela peut ou non être plus facile à retenir.
Cette commande descend toujours dans le répertoire bet traite chaque fichier qu'il contient uniquement pour -notles rejeter. Cela peut être un problème de performances si le répertoire best énorme.
-pathfonctionne différemment de -name. -namene correspond qu'au nom (du fichier ou du répertoire) tandis qu'il -pathcorrespond au chemin entier. Par exemple, observez le chemin /home/lesmana/foo/bar. -name -barcorrespondra car le nom est bar. -path "*/foo*"correspondra car la chaîne se /footrouve dans le chemin. -patha quelques subtilités que vous devez comprendre avant de l'utiliser. Lisez la page de manuel de findpour plus de détails.
Attention, ce n'est pas infaillible à 100%. Il y a des chances de "faux positifs". La façon dont la commande est écrite ci-dessus ignorera tout fichier contenant un répertoire parent dont le nom commence par b(positif). Mais il ignorera également tout fichier dont le nom commence par, bquelle que soit sa position dans l'arbre (faux positif). Cela peut être corrigé en écrivant une meilleure expression que "*/b*". Cela reste un exercice pour le lecteur.
Je suppose que vous avez utilisé aet bcomme espaces réservés et les vrais noms ressemblent plus à allosauruset brachiosaurus. Si vous mettez brachiosaurusen place, bla quantité de faux positifs sera considérablement réduite.
Au moins, les faux positifs ne seront pas supprimés, ce ne sera donc pas aussi tragique. De plus, vous pouvez vérifier les faux positifs en exécutant d'abord la commande sans -delete(mais n'oubliez pas de placer l'implicite -depth) et examinez la sortie.
find a -not -path "*/b*" -type f -depth
asaufa/b?