GNU/Linux >> Tutoriels Linux >  >> Linux

Supprimer tous les fichiers sauf dans un certain sous-répertoire avec Find ?

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 nom b 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épertoire b 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.

En relation:ado -Find Meaning- Recherche de dictionnaire !

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

Linux
  1. 3 façons de supprimer tous les fichiers d'un répertoire sauf un ou quelques fichiers avec des extensions

  2. Comment trouver des fichiers avec un certain sous-chemin ?

  3. Comment supprimer tous les fichiers avec une extension particulière dans un dossier particulier ?

  4. Comment rechercher tous les fichiers avec une taille de fichier de zéro (0) octet dans un répertoire de manière récursive

  5. Comment trouver tous les fichiers se terminant par .rb avec Linux ?

Retrouver les fichiers perdus avec Scalpel

Comment trouver tous les fichiers/dossiers avec la permission 777 sous Linux ?

Répertorier tous les fichiers d'images graphiques avec rechercher ?

Comment supprimer tous les fichiers commençant par une certaine chaîne sous Linux

Comment supprimer tous les fichiers d'un répertoire sauf certains ?

Définissez nginx.conf pour refuser toutes les connexions sauf à certains fichiers ou répertoires