Récemment, j'ai été confronté à la tâche de supprimer tous les fichiers / dossiers d'un répertoire, à l'exception de ceux correspondant à un modèle spécifique. J'ai donc préparé une commande unix sur une seule ligne pour faire le travail. Doit-il s'agir d'une seule ligne? Je suppose que non, mais c'est définitivement plus cool de cette façon!
Bien que le problème soit assez simple, j'ai été un peu surpris de la complexité de ma solution. Voici la commande que j'ai utilisée; REMARQUE: c'est une mauvaise solution car elle ne gère pas les noms de fichiers contenant des caractères de saut de ligne (ce qui n'avait pas d'importance dans ma situation).
ls | grep -v PATTERN | xargs -n1 -IREPLACE rm -rf REPLACE
Je n'ai pas utilisé la commande "find" car je ne veux pas rentrer dans les dossiers correspondant au MOTIF. Par exemple, considérez la structure de fichiers suivante:
file_foo.txt
first_dir
|
+--> contents
+--> ...
foo_dir
|
+--> anotherfile.txt
+--> morefiles.log
foo_file.txt
somefile.txt
L'utilisation du modèle "foo" ne doit supprimer que "first_dir" (et son contenu bien sûr) et "somefile.txt" ( pas "anotherfile.txt" ou "morefiles.log").
Question, existe-t-il de meilleures façons (plus élégantes et correctes) d'accomplir cela?
EDIT:
Il a été récemment porté à mon attention que "trouver" peut être une meilleure option:
find * -maxdepth 0 ! -name PATTERN -print0 | xargs -0n1 rm -rf
Cette solution gère correctement les chemins d'accès contenant des caractères de saut de ligne.
la source
Réponses:
Les exemples suivants ont été
echo
préfixés afin que vous puissiez tester les modèles avant de les utiliser réellement. Retirez leecho
pour activer lerm -rf
. Remplacerrm -ri
pour demander une confirmation.ksh a une extension de correspondance négative à son globbing:
La même syntaxe est disponible dans bash si vous définissez l'
extglob
option:zsh a sa propre syntaxe pour cela:
Il peut également utiliser la syntaxe de style ksh :
la source
shopt -s extglob
à mon fichier .bashrc, il s'agit donc maintenant d' une ligne). Parfait! Je promets un vote positif dès que ma réputation le permettra.Voici une autre
find
solution. Je ne suis pas sûr que cela ait un réel avantage sur le vôtre, mais cela n'a pas besoinxargs
et permet la rare possibilité que * s'étende à trop de noms.J'ai également ajouté
-type f
afin qu'il n'essaye pas de supprimer les répertoires.Attention:
-delete
est puissant. J'ai donné à l'un de mes fichiers de test 0 autorisations et la commande ci-dessus l'a supprimé sans hésitation.la source
-delete
par-print
pour voir s'il trouve les fichiers que vous vouliez. Si tout va bien, utilisez l'historique des commandes (par exemple, appuyez sur le bouton haut) pour revenir à la commande précédente et vous assurer que vous travaillez avec les mêmes filtres de recherche.find -delete
ne supprimera pas les répertoires non vides. Notez également quefind -maxdepth 1
correspond à "." (répertoire actuel) ce qui est vraiment mauvais. Bien que j'aime votre idée d'éliminerxargs
, on pourrait utiliserfind -exec
alternativement.find * -maxdepth 0 ! -name PATTERN -exec rm -rf '{}' \;
Vous pouvez utiliser cet exemple de script rebol http://askcodegeneration.com/keep-subversion/ à la place, qui est beaucoup plus compréhensible et qui peut gérer l'interaction utilisateur comme la sélection et la confirmation de dossier:
la source