Il y a 2 façons de lire cette question, et les réponses existantes couvrent les deux interprétations: SOIT: (a) conserver les fichiers avec les noms spécifiés directement situés dans le répertoire cible et - comme cela rm -rimplique - supprimer tout le reste, y compris les sous - répertoires - même s'ils contiennent fichiers avec les noms spécifiés; OU: (b) parcourir l'intégralité de la sous-arborescence du répertoire cible et, dans chaque répertoire, supprimer tous les fichiers sauf ceux portant les noms répertoriés.
mklement0
Réponses:
219
find [path]-type f -not -name 'textfile.txt'-not -name 'backup.tar.gz'-delete
Si vous ne spécifiez pas, -type ffind répertorie également les répertoires, que vous ne souhaitez peut-être pas.
Ou une solution plus générale utilisant la combinaison très utile find | xargs:
J'obtiens "une erreur de syntaxe près du jeton inattendu` ('"quand je le fais shopt -s extglob; rm -rf !(README|LICENSE). Une idée pourquoi?
Dennis
@nic Je ne me souviens pas, désolé. J'ai probablement fini par utiliser findl' -deleteoption.
Dennis
C'est la meilleure solution pour moi et elle fonctionne par défaut sur mon Ubuntu 12.04.4 LTS sans avoir besoin de shopt
xtian
3
@nic, @Dennis: L'erreur de syntaxe suggère que quelque chose AUTRE que ce qui a bashété utilisé, par exemple dash, où extglobn'est pas pris en charge. Cependant, dans un shell interactifbash , la commande ne fonctionnera AUSSI PAS comme indiqué, mais pour des raisons différentes. En bref: exécutez shopt -s extglobBY ITSELF; UNE FOIS AVEC SUCCÈS ACTIVÉ (vérifier avec shopt extglob), exécutez rm -rf !(README|LICENSE). (Bien qu'il extglobne soit pas encore activé, il !(...)est évalué par l'expansion de l'historique AVANT l'exécution des commandes; car cela échoue probablement, AUCUNE commande n'est exécutée et extglobn'est jamais activée.)
mklement0
2
@nic, @Dennis, @ mklement0: J'ai eu le même problème avec "erreur de syntaxe près d'un jeton inattendu (" lors de l'exécution de la commande dans un fichier .sh (#! / bin / bash) mais pas lorsque je l'exécutais dans une commande interface de ligne. Il s'est avéré qu'en plus de l' shopt -s extglobexécution dans l'interface de ligne de commande, je devais la relancer dans mon fichier de script. Cela a résolu le problème pour moi.
Cela listera tous les fichiers du répertoire courant, puis listera tous ceux qui ne correspondent pas à vos critères (attention à ce qu'ils correspondent aux noms de répertoires) puis les supprimera.
Mise à jour : en fonction de votre modification, si vous voulez vraiment tout supprimer du répertoire actuel, à l'exception des fichiers que vous avez répertoriés, cela peut être utilisé:
Il va créer un répertoire de sauvegarde /tmp_backup(vous avez les privilèges root, non?), Déplacer les fichiers que vous avez listés dans ce répertoire, supprimer récursivement tout dans le répertoire courant (vous savez que vous êtes dans le bon répertoire, n'est-ce pas?), Déplacer revenir au répertoire actuel tout de /tmp_backupet enfin, supprimer /tmp_backup.
Je choisis que le répertoire de sauvegarde soit en root, car si vous essayez de tout supprimer récursivement de root, votre système aura de gros problèmes.
Il existe certainement des façons plus élégantes de le faire, mais celui-ci est assez simple.
Fonctionne également très bien avec egrep, par exemple pour nettoyer les fichiers intermédiaires en latex:find . | egrep -v "\.tex|\.bib" | xargs rm
mtsz
commande incroyable! pour supprimer les répertoires, passez simplement à rm -r
Aris
1
Si vous souhaitez simplement supprimer tout ce qui se trouve dans le répertoire actuel, à l'exception des critères exclus: find . -maxdepth 1 | grep -v "exclude these" | xargs rm -rfonctionne beaucoup plus rapidement car il n'a pas besoin d'explorer les répertoires inutilement.
billynoah
Re findpipeline: les problèmes d'efficacité mis à part (3 commandes sont utilisées pour ce qui findpourrait faire seul), cela ne fonctionnera pas comme prévu avec les noms de fichiers avec des espaces intégrés et supprimera potentiellement les mauvais fichiers.
mklement0
Une commande qui stocke des fichiers «à enregistrer» dans un autre emplacement ( /tmp_backup) ne se termine pas bien si elle est interrompue - du point de vue de l'utilisateur, tous les fichiers ont disparu, à moins qu'ils ne sachent où aller les chercher pour les récupérer . Pour cette raison, je ne suis pas en faveur de ce type de stratégie.
Craig McQueen
20
En supposant que les fichiers portant ces noms existent à plusieurs endroits de l'arborescence de répertoires et que vous souhaitez tous les conserver:
find .-type f !-regex ".*/\(textfile.txt\|backup.tar.gz\|script.php\|database.sql\|info.txt\)"-delete
Définir GLOBIGNORE comme ceci ignore le php et le sql des caractères génériques utilisés comme "ls *" ou "rm *". Ainsi, l'utilisation de "rm *" après avoir défini la variable supprimera uniquement le fichier txt et tar.gz.
+1; Une alternative plus simple à la définition et à la restauration de la GLOBIGNOREvariable consiste à utiliser un sous-shell:(GLOBIGNORE='*.php:*.sql'; rm *)
C'est plus compliqué car vous devez prendre soin des autorisations après les avoir recopiées.
Romulus
2
@RemusAvram Vous pouvez utiliser les commutateurs appropriés avec cpou rsyncpour conserver les autorisations. Quoi qu'il en soit, ce n'est qu'une méthode alternative (donnée à titre de suggestion) qui a sa place ici, comme réponse au PO.
gniourf_gniourf
Cela peut ne pas être approprié dans de nombreuses situations où les fichiers à conserver sont activement utilisés par d'autres processus. Il est également encombrant que les fichiers à supprimer ne soient qu'un petit sous-ensemble et qu'un grand nombre de fichiers soient impliqués.
codeforester le
@codeforester: bien sûr. Mais il y a des situations où c'est approprié, cependant ... en fait, je ne vois pas vraiment le sens de votre commentaire :).
gniourf_gniourf
6
Vous pouvez écrire une boucle for pour cela ...%)
for x in*doif["$x"!="exclude_criteria"]then
rm -f $x;fidone;
Un peu tard pour l'OP, mais j'espère utile pour tous ceux qui arriveront bien plus tard par google ...
J'ai trouvé la réponse de @awi et le commentaire sur -delete de @Jamie Bullock vraiment utiles. Un utilitaire simple pour que vous puissiez le faire dans différents répertoires en ignorant à chaque fois différents noms / types de fichiers avec un minimum de frappe:
mais les noms avec des espaces sont (comme toujours) difficiles. J'ai également essayé avec Virtualbox\ VMsles citations. Il supprime toujours ce répertoire ( Virtualbox VMs).
Ne fonctionne PAS pour les fichiers. rm !(myfile.txt)supprime tout, y comprismyfile.txt
khaverim
devrait s'exécuter en shopt -s extglobpremier comme @ pl1nk l'a souligné
zhuguowei
Oui, il est très important d'activer extension de englobement ( extglob ) en bash, je fais cela dans une base de routine quotidienne, sur quelques Mac dans les laboratoires: shopt -s extglobpuis cd /Users/alumno/et enfin rm -rf !(Applications|Virtualbox*VMs|Downloads|Documents|Desktop|Public|Library) Lire au sujet étendu englobement ici
juanfal
4
Juste:
rm $(ls -I "*.txt")#Deletes file type except *.txt
Après cela, parcourez tous les fichiers du répertoire que vous souhaitez exclure, en vérifiant si le nom de fichier se trouve dans le tableau que vous ne souhaitez pas exclure; si ce n'est pas le cas, supprimez le fichier.
for file in*;doif[[!" ${files[@]} "~="$file"]];then
rm "$file"fidone
La comparaison des expressions rationnelles est incorrecte - elle préservera tout fichier dont le nom est une sous-chaîne de l'un des fichiers protégés (bien que les espaces environnants atténuent quelque peu cela; mais les noms de fichiers peuvent contenir des espaces). Vous devez collecter un tableau de tous les fichiers, puis soustraire les fichiers que vous souhaitez exclure de ce tableau, puis supprimer les fichiers restants.
tripleee
-1
Comme personne ne l'a encore mentionné, dans un cas particulier:
OLD_FILES=`echo *`... create new files ...
rm -r $OLD_FILES
(ou tout simplement rm $OLD_FILES)
ou
OLD_FILES=`ls *`... create new files ...
rm -r $OLD_FILES
Vous devrez peut-être utiliser shopt -s nullglobsi certains fichiers peuvent être présents ou absents:
La réponse existante de Leonardo Hermoso le fait avec moins de bugs. Cela échouera pour les noms de fichiers avec des espaces; l'utilisation d'un tableau résout avec élégance ce problème particulier (et évite également de manière moins cruciale d'utiliser des majuscules pour ses variables privées, ce qui est généralement à éviter).
tripleee
-3
Plutôt que d'aller pour une commande directe, veuillez déplacer les fichiers requis vers le répertoire temporaire en dehors du répertoire actuel. Supprimez ensuite tous les fichiers à l'aide de rm *ou rm -r *.
Déplacez ensuite les fichiers requis vers le répertoire actuel.
Cela peut ne pas être approprié dans de nombreuses situations où les fichiers à conserver sont activement utilisés par d'autres processus. Il est également encombrant que les fichiers à supprimer ne soient qu'un petit sous-ensemble et qu'un grand nombre de fichiers soient impliqués.
codeforester le
-3
Supprimer tout exclure file.name:
ls -d /path/to/your/files/*|grep -v file.name|xargs rm -rf
Cela échouera horriblement et pourrait entraîner une perte de données si votre répertoire / fichiers contient des espaces ou des caractères inhabituels. Vous ne devriez jamais analyser ls. mywiki.wooledge.org/ParsingLs
rm -r
implique - supprimer tout le reste, y compris les sous - répertoires - même s'ils contiennent fichiers avec les noms spécifiés; OU: (b) parcourir l'intégralité de la sous-arborescence du répertoire cible et, dans chaque répertoire, supprimer tous les fichiers sauf ceux portant les noms répertoriés.Réponses:
Si vous ne spécifiez pas,
-type f
find répertorie également les répertoires, que vous ne souhaitez peut-être pas.Ou une solution plus générale utilisant la combinaison très utile
find | xargs
:par exemple, supprimez tous les fichiers non txt du répertoire courant:
La combinaison
print0
et-0
est nécessaire s'il y a des espaces dans l'un des noms de fichiers qui doivent être supprimés.la source
find . -type f -not -name '*ignore1' -not -name '*ignore2' | xargs rm
-print0 | xargs -0 rm --
vous pouvez simplement-delete
L'extglob (Extended Pattern Matching) doit être activé dans BASH (s'il n'est pas activé):
la source
shopt -s extglob; rm -rf !(README|LICENSE)
. Une idée pourquoi?find
l'-delete
option.bash
été utilisé, par exempledash
, oùextglob
n'est pas pris en charge. Cependant, dans un shell interactifbash
, la commande ne fonctionnera AUSSI PAS comme indiqué, mais pour des raisons différentes. En bref: exécutezshopt -s extglob
BY ITSELF; UNE FOIS AVEC SUCCÈS ACTIVÉ (vérifier avecshopt extglob
), exécutezrm -rf !(README|LICENSE)
. (Bien qu'ilextglob
ne soit pas encore activé, il!(...)
est évalué par l'expansion de l'historique AVANT l'exécution des commandes; car cela échoue probablement, AUCUNE commande n'est exécutée etextglob
n'est jamais activée.)shopt -s extglob
exécution dans l'interface de ligne de commande, je devais la relancer dans mon fichier de script. Cela a résolu le problème pour moi.find . | grep -v "excluded files criteria" | xargs rm
Cela listera tous les fichiers du répertoire courant, puis listera tous ceux qui ne correspondent pas à vos critères (attention à ce qu'ils correspondent aux noms de répertoires) puis les supprimera.
Mise à jour : en fonction de votre modification, si vous voulez vraiment tout supprimer du répertoire actuel, à l'exception des fichiers que vous avez répertoriés, cela peut être utilisé:
Il va créer un répertoire de sauvegarde
/tmp_backup
(vous avez les privilèges root, non?), Déplacer les fichiers que vous avez listés dans ce répertoire, supprimer récursivement tout dans le répertoire courant (vous savez que vous êtes dans le bon répertoire, n'est-ce pas?), Déplacer revenir au répertoire actuel tout de/tmp_backup
et enfin, supprimer/tmp_backup
.Je choisis que le répertoire de sauvegarde soit en root, car si vous essayez de tout supprimer récursivement de root, votre système aura de gros problèmes.
Il existe certainement des façons plus élégantes de le faire, mais celui-ci est assez simple.
la source
find . | egrep -v "\.tex|\.bib" | xargs rm
find . -maxdepth 1 | grep -v "exclude these" | xargs rm -r
fonctionne beaucoup plus rapidement car il n'a pas besoin d'explorer les répertoires inutilement.find
pipeline: les problèmes d'efficacité mis à part (3 commandes sont utilisées pour ce quifind
pourrait faire seul), cela ne fonctionnera pas comme prévu avec les noms de fichiers avec des espaces intégrés et supprimera potentiellement les mauvais fichiers./tmp_backup
) ne se termine pas bien si elle est interrompue - du point de vue de l'utilisateur, tous les fichiers ont disparu, à moins qu'ils ne sachent où aller les chercher pour les récupérer . Pour cette raison, je ne suis pas en faveur de ce type de stratégie.En supposant que les fichiers portant ces noms existent à plusieurs endroits de l'arborescence de répertoires et que vous souhaitez tous les conserver:
la source
Vous pouvez utiliser la variable d'environnement GLOBIGNORE dans Bash.
Supposons que vous vouliez supprimer tous les fichiers sauf php et sql, vous pouvez alors faire ce qui suit -
Définir GLOBIGNORE comme ceci ignore le php et le sql des caractères génériques utilisés comme "ls *" ou "rm *". Ainsi, l'utilisation de "rm *" après avoir défini la variable supprimera uniquement le fichier txt et tar.gz.
la source
GLOBIGNORE
variable consiste à utiliser un sous-shell:(GLOBIGNORE='*.php:*.sql'; rm *)
Je préfère utiliser la liste de sous-requêtes:
la source
Puisque personne ne l'a mentionné:
la source
cp
oursync
pour conserver les autorisations. Quoi qu'il en soit, ce n'est qu'une méthode alternative (donnée à titre de suggestion) qui a sa place ici, comme réponse au PO.:)
.Vous pouvez écrire une boucle for pour cela ...%)
la source
Un peu tard pour l'OP, mais j'espère utile pour tous ceux qui arriveront bien plus tard par google ...
J'ai trouvé la réponse de @awi et le commentaire sur -delete de @Jamie Bullock vraiment utiles. Un utilitaire simple pour que vous puissiez le faire dans différents répertoires en ignorant à chaque fois différents noms / types de fichiers avec un minimum de frappe:
rm_except (ou ce que vous voulez lui donner)
par exemple pour tout supprimer sauf pour les fichiers texte et foo.bar:
Similaire à @mishunika, mais sans la clause if.
la source
Si vous utilisez
zsh
ce que je recommande fortement.Avec
extended_glob
la source
L'essayer a fonctionné avec:
mais les noms avec des espaces sont (comme toujours) difficiles. J'ai également essayé avec
Virtualbox\ VMs
les citations. Il supprime toujours ce répertoire (Virtualbox VMs
).la source
rm !(myfile.txt)
supprime tout, y comprismyfile.txt
shopt -s extglob
premier comme @ pl1nk l'a soulignéshopt -s extglob
puiscd /Users/alumno/
et enfinrm -rf !(Applications|Virtualbox*VMs|Downloads|Documents|Desktop|Public|Library)
Lire au sujet étendu englobement iciJuste:
Ou:
la source
ls
sortie peut devenir un problème. Voir ici pour des informations détaillées.Rendez les fichiers immuables. Même root ne sera pas autorisé à les supprimer.
Tous les autres fichiers ont été supprimés.
Finalement, vous pouvez les réinitialiser mutables.
la source
Ceci est similaire au commentaire de @ siwei-shen mais vous avez besoin du
-o
drapeau pour faire plusieurs modèles. Le-o
drapeau signifie «ou»find . -type f -not -name '*ignore1' -o -not -name '*ignore2' | xargs rm
la source
Vous pouvez le faire avec deux séquences de commandes. Définissez d'abord un tableau avec le nom des fichiers que vous ne souhaitez pas exclure:
Après cela, parcourez tous les fichiers du répertoire que vous souhaitez exclure, en vérifiant si le nom de fichier se trouve dans le tableau que vous ne souhaitez pas exclure; si ce n'est pas le cas, supprimez le fichier.
la source
Comme personne ne l'a encore mentionné, dans un cas particulier:
(ou tout simplement
rm $OLD_FILES
)ou
Vous devrez peut-être utiliser
shopt -s nullglob
si certains fichiers peuvent être présents ou absents:sans nullglob,
echo *.sh *.bash
peut vous donner "a.sh b.sh * .bash".(Cela dit, je préfère moi-même cette réponse , même si elle ne fonctionne pas sous OSX)
la source
Plutôt que d'aller pour une commande directe, veuillez déplacer les fichiers requis vers le répertoire temporaire en dehors du répertoire actuel. Supprimez ensuite tous les fichiers à l'aide de
rm *
ourm -r *
.Déplacez ensuite les fichiers requis vers le répertoire actuel.
la source
Supprimer tout exclure file.name:
la source