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 :
-prune
empêche find de descendre dans un répertoire. En d'autres termes-prune
ignore le contenu du répertoire. Dans votre cas-name b -prune
signifie que lorsque find atteint un répertoire avec le nomb
il ignorera le répertoire, y compris tous les sous-répertoires.-depth
fait 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épertoireb
son contenu a déjà été traité. Ainsi-prune
est inefficace avec-depth
en vigueur.-delete
implique-depth
afin qu'il puisse d'abord supprimer le contenu, puis le répertoire vide.-delete
refuse 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