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

123

Je dois supprimer tous les fichiers d'un répertoire, mais en exclure certains. Par exemple, dans un répertoire contenant les fichiers a b c ... z, je dois tout supprimer, à l'exception de uet p. Y a-t-il un moyen facile de faire ceci?

Un coup de feu
la source
Les réponses ci-dessous sont bien meilleures, mais vous pouvez simplement créer des fichiers en lecture seule, les supprimer tous, puis rétablir leurs autorisations d'origine (tant que vous n'utilisez pas rm -f). Vous devez connaître les autorisations à restaurer et savoir que rien ne nécessite un accès en écriture lors du processus. C'est pourquoi les autres réponses sont meilleures.
Joe
1
Si vous souhaitez également supprimer les fichiers cachés, exécutez-les shopt -s dotglobavant de les exécuter rm (...).

Réponses:

108

Ce que je fais dans ces cas est de taper

rm *

Ensuite , je presse Ctrl+ X, *pour développer * dans tous les noms de fichiers visibles.

Ensuite, je peux simplement supprimer les deux fichiers que je souhaite garder de la liste et enfin exécuter la ligne de commande.

Der Hochstapler
la source
25
Je suppose que cela ne fonctionne que tant que la liste de fichiers qui *s’allonge ne s’allonge pas trop. : -}
Frerich Raabe
9
Echap suivi de * élargira également le "*".
slowpoison
2
@SantoshKumar: Cela n'a aucun sens pour moi. L'expansion fonctionnera toujours, cela ne dépend pas de la commande que vous souhaitez utiliser par la suite.
Der Hochstapler
2
@OliverSalzburg Désolé, la combinaison est un peu déroutant. Je pense que vous devriez écrire comme Ctrl+ Shift+ x+*
Santosh Kumar le
2
@SantoshKumar: Mais ce n'est pas la combinaison.
Der Hochstapler
143

Pour rmtous sauf u,pen bash, tapez simplement:

rm !(u|p)

Cela nécessite la définition de l'option suivante:

shopt -s extglob

Voir aussi: glob - Greg's Wiki

sparkie
la source
1
vous devez avoir 'extglobbing' actif: shopt -s extglob
sparkie
18
Vous devez shopt -s extglob, @Ashot. En outre, il ne s'agit que de fichiers, pas de répertoires, c'est pourquoi j'ai supprimé les -rfoptions de votre commande.
Slhck
4
Si vous avez besoin d'exclure un fichier d'une sélection de fichiers, essayez ceci: rm !(index).html. Cela supprimera tous les fichiers se terminant par ".html" à l'exception de "index.html".
Mzuther
71

Vous pouvez utiliser find

find . ! -name u ! -name p -maxdepth 1 -type f -delete
  • ! nie la prochaine expression
  • -name spécifie un nom de fichier
  • -maxdepth 1fera que le processus de recherche ne contienne que le répertoire spécifié ( findpar défaut, il traverse les répertoires)
  • -type f traitera uniquement les fichiers (et pas par exemple les répertoires)
  • -delete va supprimer les fichiers

Vous pouvez ensuite régler les conditions en consultant la page de manuel de find.

Mise à jour

  • Gardez à l'esprit que l'ordre des éléments des expressions est important (voir la documentation)
  • Testez d'abord votre commande en utilisant -printau lieu de-delete

    find . ! -name u ! -name p -maxdepth 1 -type f -print
Matteo
la source
5
ordre des prédicats est critique ici. Si l'on met -deletejuste après, .ce sera une catastrophe (tous les fichiers de la CWD seront supprimés)
Michał Šrajer
Cela pourrait être écrit de manière plus compacte commefind . -maxdepth 1 -type f -name '[^up]' -delete
kojiro
4
@kojiro oui, mais uniquement pour les fichiers ne contenant qu'une lettre. Avec des noms plus complexes, l'expression rationnelle pourrait être un désordre.
Matteo
2
findest mon meilleur ami, surtout quand il y a trop de fichiers dans le monde entier
Terence Johnson
43

Facile:

mvles fichiers que vous voulez dans un répertoire supérieur, rmle répertoire et ensuite mvles retourner.

utilisateur176581
la source
13
Bien sûr, mv les dans un répertoire plus élevé. Essayez de ne pas les envoyer dans un sous-répertoire que vous supprimez ...
Konerak
@Konerak: rmsans -rsupprimer les sous-répertoires.
Reinierpost
11
Cela écrasera les fichiers portant le même nom dans le répertoire de destination
Matteo le
7
Je vote en faveur de cela car, même si cela peut être pratique, il est également non atomique et supprime efficacement tous les fichiers du répertoire pendant une courte période; cela ne serait pas acceptable si, par exemple, les fichiers sont partagés sur le réseau.
Sam hocevar
15

Un peu similaire à cette réponse , mais aucune option particulière sont nécessaires, pour autant que je sache ce qui suit est « ancienne » fonctionnalités prises en charge par un (vaguement) / bin / sh ressemblant shell (par exemple bash, zsh, ksh, etc.)

rm [^up]
Hlovdal
la source
2
Cela fonctionne pour les noms de fichiers à 1 caractère. Pour les noms plus longs, la réponse de sparkie est préférable.
Glenn Jackman
3
Quel serait le problème avec rm [^up]*? Je fais des choses similaires assez souvent.
un CVn
3
@ MichaelKjörling - cela effacerait tous les fichiers commençant par u ou p, pas seulement ceux portant les noms u et p. Je pense que le PO (@Ashot) signifiait les z et u, p, etc. symboliquement et non littéralement.
Sudipta Chatterjee, le
4
@HobbesofCalvin Cela effacerait tous les fichiers ne commençant pas par u ou p, pas ceux commençant par eux.
Rjmunro
@rjmunro - merci, raté celui-là! :)
Sudipta Chatterjee le
11

Le faire sans trouver:

ls | grep -v '(u|p)' | xargs rm

(Edit: "u" et "v", comme à d'autres endroits ici, sont utilisés comme versions génériques de expressions rationnelles entières. Évidemment, vous voudrez bien faire attention à ancrer vos expressions rationnelles pour éviter de faire correspondre trop de choses.)

Vous allez certainement vouloir un script si vous allez faire beaucoup de cela, comme d'autres l'ont suggéré.

tquid
la source
grep ne gérera pas les expressions rationnelles étendues par défaut: utilisez -Eouegrep
Matteo
2
cela exclura tout fichier contenant un uou unp
Matteo
@ Matteo Non, ce ne sera pas le cas. Le grep n'est pas grepping les fichiers, il grepte le résultat de la commande ls. Vous pensez à quelque chose comme grep -L (u|p)' * | xargs rm-Lsignifie les noms de fichiers de liste ne contenant pas de correspondance.
rjmunro
4
Oh, vous voulez dire tout fichier dont le nom contient uou ppas un fichier contenant un uou p. C'est correct. Vous pouvez réparer en utilisantegrep -v '^(u|p)$'
rjmunro
1
Voici tout supprimer sauf ces allumettes! ls | grep -v 'vuze\|progs' | xargs rm -rf
Nick
6

En zsh:

setopt extended_glob  # probably in your .zshrc

ensuite

rm ^(u|p)

ou

rm *~(u|p)

La seconde fonctionnera même si vous avez ^en $histcharssubstitution de l' histoire, et bien sûr vous pouvez mettre un glob arbitraire avant ~.

poolie
la source
5

GLOBIGNORE prend une liste séparée par deux points

GLOBIGNORE=u:p
rm *
W_Whalley
la source
12
Cela ne fonctionne pas sur mon shell (GNU bash 4.1.5 (1)). Assurez-vous de le tester d'abord avec quelque chose d'un peu moins nocif querm dans un répertoire de tests!
un CVn
3

À l'époque des disquettes, j'avais un exécutable DOS appelé "Except" qui déplacerait temporairement les éléments du répertoire en cours et exécuterait une commande. Vous pourriez donc dire:

sauf * .txt del *. *

pour tout supprimer sauf vos fichiers texte.

Ce serait une chose assez triviale à implémenter en tant que script shell et si c'est le genre de chose que vous ferez probablement plus de deux fois, cela semble être une bonne idée.

Bill K
la source
2
Cela m'a rappelé la même chose. Mais sortir temporairement du dossier peut ne pas être une bonne idée à l'ère du multitâche :)
Sedat Kapanoglu
3
 find . -maxdepth 1 ! -name "u" ! -name "p" -type f -exec rm -rf {} \;

Cela supprimera tous les fichiers sauf u et p sous unix

utilisateur1803687
la source
2

Pour ceux qui préfèrent spécifier des motifs d'exclusion complexes arbitraires (couvrant tous les noms de fichiers affectés) dans un style reacxp complet, emacs, posix-awk ou posix-extended (voir la page de manuel find), je recommanderais celui-ci. Il exclut uet pdans le répertoire en cours dans cet exemple. Cela peut être utile pour les scripts.

find -regextype posix-awk ! -regex './(u|p)' -print0 | xargs -0 rm -rf
sparkie
la source
Vous devez spécifier un répertoire avant l'expression (`find. -Regextype ...).
Matteo
-regextypene fonctionnera que sur les versions GNU
Matteo le
non - ma version de recherche (debian squeeze) ne nécessite définitivement pas de répertoire explicite avant l'expression si le répertoire en cours doit être utilisé
sparkie
@sparke: cela ne fonctionne que sur les implémentations GNU
Matteo
@sparkie: ne définissant pas le répertoire (premier paramètre), il finds'agit d'une extension de findcommande GNU . La même chose s'applique pour l' -regextypeoption. En outre, votre commande supprimera également les fichiers des sous-répertoires, alors que la question d'origine visait clairement à définir les fichiers d'un répertoire.
Mikko Rantalainen
1

J'utilise toujours:

rm [a-o,q-t,v-z]*

Cela vous permettra de définir la granularité souhaitée. Donc, si vous voulez supprimer les fichiers O et Z, vous pouvez utiliser:

rm [a-o,z]*
J Baron
la source
1

Encore une autre version utilisant xargs:

ls -1 | grep -v do_not_delete | xargs -I files rm "files"

Notez que cela xargs -Iest nécessaire pour gérer correctement les noms de fichiers, y compris les espaces.

sebhofer
la source
1

Encore un autre:

for FILE in ./*; do if [[ $FILE != ./u* ]] || [[ $FILE != ./p* ]];then rm $FILE; fi; done;

C'est un peu long et je ne sais pas si vous pourriez facilement en faire une fonction qui pourrait facilement contenir un nombre arbitraire d'arguments, mais cela fonctionne bien.

Et c'est de la pure bonté.

dylnmc
la source
1

Voici une autre variante. Vous pouvez taper:

rm -i *

ou:

rm --interactive *

Nous rmvous demanderons donc de confirmer la suppression de chaque fichier.

Idzikovsky
la source
1

Utilisation:

find . -type f ! -name 'u' ! -name 'p' ! -name '*.ext' -delete
find . -type d ! -name 'u' ! -name 'p' ! -name '*.ext' -delete

afin de supprimer tous les fichiers, y compris les répertoires, à l'exception des fichiers u, p et .ext.

Renzo Fabián
la source
0

Un moyen simple et difficile à gâcher: disons que vous voulez tout supprimer sauf * .pdf:

mkdir tmp
mv *.pdf tmp
rm *
mv tmp/* .
rm -r tmp
talloaktrees
la source