Question Exclure les sous-dossiers contenant des fichiers spécifiques dans rm -rf / folder / * récursif


Je me demande s'il est possible de spécifier une condition élégante (paramètre peut-être?) Dans rm -rf /folder/* ne pas supprimer ses sous-dossiers, qui contiennent des fichiers portant le nom "dontshoot.txt".

Je n'ai pas pu en trouver jusqu'à présent.

Merci d'avance pour votre aide!


4
2018-06-13 11:47


origine


à ma connaissance rm ne peut pas exclure des patterns, vous devrez écrire une fonction ou un script pour ce faire. - Cobra_Fast


Réponses:


Vous pouvez simplement utiliser find comme ça

find some_folder ! -name dontshoot.txt -delete

Cela supprimera tous les fichiers et dossiers de manière récursive, sauf le dontshoot.txt des dossiers. Comme indiqué dans les autres commentaires, il est toujours utile de le tester sans le supprimer, ce qui peut simplement être fait comme ceci.

find some_folder ! -name dontshoot.txt 

Cependant, cela listera tous les dossiers, même ceux qui contiennent dontshoot.txt mais ils ne seront pas supprimés car ils ne seront pas vider lors de l'utilisation -delete.

Modifier:

Je suis d'accord que l'interprétation de Fedorqui de la question est plus raisonnable que la mienne. Pour supprimer uniquement les dossiers ne contenant pas dontshoot.txt quelque part au plus profond de leur structure arborescente, une terrible solution inefficace serait

find some_folder -type d -exec \
   sh -c "find {} -name dontshoot.txt | grep -q '' || echo rm -fr {}" \;

Explication:

L'extérieur find commande traverse récursivement à travers some_folder trouver tous les répertoires (-type d) et en cours d'exécution (-exec) la commande shell donnée en remplaçant {} par le chemin d'accès relatif au répertoire trouvé.

le find commande à l'intérieur du shell recherche les répertoires trouvés pour dontshoot.txt. S'il ne trouve rien, il n'y aura aucune sortie transmise à grep -q ''  qui reviendra donc False et la dernière partie sera exécutée ce qui supprimera le répertoire complet (qui ne contient certainement pas dontshoot.txt) récursivement.

En bref, il traverse tous les répertoires et supprime ceux qui ne contiennent pas dontshoot.txt quelque part à l'intérieur d'eux.


7
2018-06-13 12:00



J'ai un doute: et si on avait un dossier t / avec dontshoot.txt et otherfile.txt? Je pense que votre code supprimerait le otherfile.txt, même si je suppose que cela ne devrait pas être basé sur l'OP. - fedorqui
Oui, vous avez raison, j'ai étendu la réponse à votre interprétation plus raisonnable de la question. - buergi
Félicitations, c'est une excellente réponse! - fedorqui


Il n'est pas possible de les exclure rm commander.

Vous pouvez faire quelque chose comme ça:

for dir in /folder/*
do
  echo $dir
  if [ ! -f "$dir/dontshoot.txt" ]; then
    rm -rf "$dir"
   fi
done

Important:

Vérifiez avec ls au lieu de rm avant d'exécuter.


3
2018-06-13 11:52



J'ai été voté et abaissé en même temps! - fedorqui
Ce n'est pas moi, je le jure! ; D Merci pour votre réponse, je le vérifierai. - mr.nothing
@ mr.nothing, toujours essayer votre commande avec ls avant de l'utiliser avec rm! - fedorqui
@fedorqui Probablement la meilleure solution. J'ai essayé de faire quelque chose avec find, mais je ne pense pas que cette condition puisse être compensée. - glglgl
Le problème avec cette solution est que cela ne fonctionnera pas de manière récursive. Cependant, la question ne précise pas si cela est voulu ou non. - buergi


La fonction suivante pourrait fonctionner, mais je n'ai pas eu le temps de la tester.

// $1 = directory to remove
// $2 = exclude pattern
function rmx()
{
    rm -f $(find $1 * | grep -v $2)
}

Appel comme

rmx get/rid/of/this/ ".*?not-these-files.*?"

Peut-être que cela peut au moins servir d'idée sur une façon d'aborder ce problème ...


1
2018-06-13 11:58



findest la bonne façon, mais de cette façon est compliqué, il est beaucoup plus facile d'exclure les fichiers dans la recherche tout de suite et d'utiliser -delete drapeau. Consultez ma réponse pour un exemple complet. - buergi