Comment supprimer plusieurs fichiers à la fois dans Bash sous Linux?

103

J'ai cette liste de fichiers sur un serveur Linux:

abc.log.2012-03-14
abc.log.2012-03-27
abc.log.2012-03-28
abc.log.2012-03-29
abc.log.2012-03-30
abc.log.2012-04-02
abc.log.2012-04-04
abc.log.2012-04-05
abc.log.2012-04-09
abc.log.2012-04-10

J'ai supprimé les fichiers journaux sélectionnés un par un, en utilisant la commande rm -rfci-dessous:

rm -rf abc.log.2012-03-14
rm -rf abc.log.2012-03-27
rm -rf abc.log.2012-03-28

Existe-t-il un autre moyen de supprimer les fichiers sélectionnés à la fois?

user1253847
la source
4
Et "Dites GNU / Linux, pas seulement Linux", j'entends quelqu'un tonner des sièges arrière.
Boris Stitnicky
8
Au fait, pourquoi le -rf? S'agit-il de dossiers? f est forcer, r est récursif. Cela fonctionnera si ce n'est qu'un fichier mais soyez prévenu, utiliser -rf à chaque fois que vous voulez supprimer quelque chose est très (très) (très très) dangereux. (et vous devriez ajouter la balise "bash" car "linux" est trop large.
Depado
@BorisStitnicky - Je suis curieux de savoir pourquoi le GNUest nécessaire?
user66001
2
@ user66001: Pour l'avis du projet GNU à ce sujet: gnu.org/gnu/linux-and-gnu.html . Je ne prends aucune position sur la question, du moins pas ici, et ce n’est pas le lieu d’en débattre.
Keith Thompson le
2
@BorisStitnicky - Pas besoin de débattre, était complètement ignorant, et ce lien m'a donné le niveau d'information que je recherchais +1
user66001

Réponses:

159

Bash prend en charge toutes sortes de caractères génériques et d'extensions.

Votre cas exact serait traité par l' expansion d'accolades , comme ceci:

$ rm -rf abc.log.2012-03-{14,27,28}

Ce qui précède se développerait en une seule commande avec les trois arguments et équivaudrait à taper:

$ rm -rf abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28

Il est important de noter que cette expansion est effectuée par le shell, avant rmmême d'être chargé.

se détendre
la source
N'utilisez pas "rm" si vous souhaitez restaurer les fichiers à l'avenir. Vous pouvez utiliser l'utilitaire "rm-trash": github.com/nateshmbhat/rm-trash
Natesh bhat
75

Utilisez un caractère générique ( *) pour faire correspondre plusieurs fichiers.

Par exemple, la commande ci-dessous supprimera tous les fichiers dont le nom commence par abc.log.2012-03-.

rm -f abc.log.2012-03-*

Je vous recommande de courir ls abc.log.2012-03-*pour lister les fichiers afin que vous puissiez voir ce que vous allez supprimer avant d'exécuter la rmcommande.

Pour plus de détails, reportez-vous à la page de manuel Bash sur l' extension des noms de fichiers .

dogbane
la source
Très utile, mais il ne demande pas de confirmation pour supprimer. Fait attention.
nuriselcuk
1
@nuriselcuk vous pouvez ajouter -i afin d'obtenir la confirmation de chaque fichier supprimé.
Felipe Romero
A travaillé comme un charme sur AWS Ec2-Instance exécutant Amazon Linux 1 :) Merci.
Kyle Bridenstine
41

Si vous souhaitez supprimer tous les fichiers dont les noms correspondent à une forme particulière, un caractère générique (modèle global) est la solution la plus simple. Quelques exemples:

$ rm -f abc.log.*             # Remove them all
$ rm -f abc.log.2012*         # Remove all logs from 2012
$ rm -f abc.log.2012-0[123]*  # Remove all files from the first quarter of 2012

Les expressions régulières sont plus puissantes que les caractères génériques; vous pouvez envoyer la sortie de grepà rm -f. Par exemple, si certains des noms de fichiers commencent par "abc.log"et d'autres par "ABC.log", grepvous permet de faire une correspondance insensible à la casse:

$ rm -f $(ls | grep -i '^abc\.log\.')

Cela posera des problèmes si l'un des noms de fichier contient des caractères amusants, y compris des espaces. Faites attention.

Quand je fais cela, j'exécute la ls | grep ...commande en premier et je vérifie qu'elle produit la sortie que je veux - surtout si j'utilise rm -f:

$ ls | grep -i '^abc\.log\.'
(check that the list is correct)
$ rm -f $(!!)

où se !!développe à la commande précédente. Ou je peux taper la flèche vers le haut ou Ctrl-P et modifier la ligne précédente pour ajouter la rm -fcommande.

Cela suppose que vous utilisez le shell bash. Certains autres shells, en particulier csh et tcsh et certains shells plus anciens dérivés de sh, peuvent ne pas prendre en charge la $(...)syntaxe. Vous pouvez utiliser la syntaxe de backtick équivalente:

$ rm -f `ls | grep -i '^abc\.log\.'`

La $(...)syntaxe est plus facile à lire, et si vous êtes vraiment ambitieux, elle peut être imbriquée.

Enfin, si le sous-ensemble de fichiers que vous souhaitez supprimer ne peut pas être facilement exprimé avec une expression régulière, une astuce que j'utilise souvent est de lister les fichiers dans un fichier texte temporaire, puis de le modifier:

$ ls > list
$ vi list   # Use your favorite text editor

Je peux ensuite modifier le listfichier manuellement, en ne laissant que les fichiers que je souhaite supprimer, puis:

$ rm -f $(<list)

ou

$ rm -f `cat list`

(Encore une fois, cela suppose qu'aucun des noms de fichier ne contient de caractères amusants, en particulier des espaces.)

Ou, lors de l'édition du listfichier, je peux ajouter rm -f au début de chaque ligne et ensuite:

$ . ./list

ou

$ source ./list

L'édition du fichier est également l'occasion d'ajouter des guillemets si nécessaire, par exemple en changeant rm -f foo baren rm -f 'foo bar'.

Keith Thompson
la source
8

Utilisez simplement la sélection multiligne dans sublime pour combiner tous les fichiers en une seule ligne et ajoutez un espace entre chaque nom de fichier, puis ajoutez rmau début de la liste. Ceci est surtout utile lorsqu'il n'y a pas de modèle dans les noms de fichiers que vous souhaitez supprimer.

[$]> rm abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28 abc.log.2012-03-29 abc.log.2012-03-30 abc.log.2012-04-02 abc.log.2012-04-04 abc.log.2012-04-05 abc.log.2012-04-09 abc.log.2012-04-10
Andy
la source
Cela devrait être la réponse acceptée car elle répond explicitement à la question posée. C'est plus convivial pour les personnes qui sont venues ici de Google.
ATLief
5

Un joker fonctionnerait bien pour cela, bien que pour être sûr, il serait préférable de rendre l'utilisation du joker aussi minime que possible, donc quelque chose du genre:

rm -rf abc.log.2012-*

Bien qu'à première vue, ne s'agit-il que de fichiers uniques? L'option récursive ne devrait pas être nécessaire si aucun de ces éléments n'est un répertoire, il est donc préférable de ne pas l'utiliser, juste pour la sécurité.

crosse1991
la source
2

Je ne suis pas un gourou de Linux, mais je crois que vous voulez diriger votre liste de fichiers de sortie vers xargs rm -rf. J'ai utilisé quelque chose comme ça dans le passé avec de bons résultats. Testez d'abord un exemple de répertoire!

EDIT - J'ai peut-être mal compris, sur la base des autres réponses qui apparaissent. Si vous pouvez utiliser des caractères génériques, tant mieux. J'ai supposé que votre liste originale que vous aviez affichée était générée par un programme pour vous donner votre "sélection", donc j'ai pensé que le piping xargsserait la voie à suivre.

Dave
la source
-1

si vous souhaitez supprimer tous les fichiers appartenant à un répertoire à la fois. Par exemple: le nom de votre répertoire est "log" et le répertoire "log" comprend les fichiers abc.log.2012-03-14, abc.log.2012-03-15, ... etc. Vous devez être au-dessus du répertoire du journal et:

rm -rf /log/*
Alican
la source