Je souhaite supprimer de manière récursive tous les fichiers non consultés depuis un certain temps dans le dossier a , sauf tous les fichiers du sous-dossier b .
find a ( -name b -prune ) -o -type f -delete
Cependant, j'obtiens un message d'erreur :
find :l'action -delete active automatiquement -depth, mais -prune ne fait
rien lorsque -depth est activé. Si vous voulez continuer malgré tout,
utilisez simplement explicitement l'option -depth.
Ajout de -depth provoque tous les fichiers dans b à inclure, qui ne doit pas arriver.
Quelqu'un connaît-il un moyen sûr de faire fonctionner cela ?
Réponse acceptée :
une façon est d'utiliser -exec rm au lieu de -delete .
find a ( -name b -prune ) -o -type f -exec rm {} +
utilisez alternativement -not -path au lieu de -prune :
find a -not -path "*/b*" -type f -delete
Explication pourquoi -prune entre en collision avec -delete :
trouver des plaintes lorsque vous essayez d'utiliser -delete avec -prune car -delete implique -depth et -depth fait -prune inefficace.
observer le comportement de find 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 quant à la commande dans un seul répertoire. Mais il y a une garantie qu'un répertoire est traité avant son contenu. Remarque foo/ avant tout foo/* et foo/bar avant tout foo/bar/* .
Ceci 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 les foo/* apparaître avant foo/ . Idem avec foo/bar .
plus d'explications :
-pruneempêche find de descendre dans un répertoire. En d'autres termes-pruneignore le contenu du répertoire. Dans votre cas-name b -prunesignifie que lorsque find atteint un répertoire avec le nombil ignorera le répertoire, y compris tous les sous-répertoires.-depthfait find pour traiter le contenu d'un répertoire avant le répertoire lui-même. Cela signifie qu'au moment où find arrive à traiter l'entrée de répertoirebson contenu a déjà été traité. Ainsi-pruneest inefficace avec-depthen vigueur.-deleteimplique-depthafin qu'il puisse d'abord supprimer le contenu, puis le répertoire vide.-deleterefuse de supprimer les répertoires non vides.
Explication de la méthode alternative :
find a -not -path "*/b*" -type f -delete
Cela peut ou non être plus facile à retenir.
Cette commande descend toujours dans le répertoire b et traite chaque fichier qu'il contient uniquement pour -not pour les rejeter. Cela peut être un problème de performances si le répertoire b est énorme.
-path fonctionne différemment de -name . -name correspond uniquement au nom (du fichier ou du répertoire) tandis que -path correspond à l'ensemble du chemin. Par exemple observez le chemin /home/lesmana/foo/bar . -name bar correspondra car le nom est bar . -path "*/foo*" correspondra car la chaîne /foo est dans le chemin. -path a quelques subtilités que vous devez comprendre avant de l'utiliser. Lisez la page de manuel de find pour plus de détails.
Attention, ce n'est pas 100% infaillible. Il y a des risques de "faux positifs". La façon dont la commande est écrite au-dessus ignorera tout fichier qui a un répertoire parent dont le nom commence par b (positif). Mais il ignorera également tout fichier dont le nom commence par b quelle 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é a et b comme espaces réservés et les vrais noms ressemblent plus à allosaurus et brachiosaurus . Si vous mettez brachiosaurus à la place de b alors le nombre de faux positifs sera considérablement réduit.
Au moins les faux positifs ne seront pas supprimé, donc ce ne sera 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 le -depth implicite ) et examinez la sortie.
find a -not -path "*/b*" -type f -depth