Comment supprimer plusieurs fichiers avec un préfixe et un suffixe communs?

21

J'ai de nombreux fichiers nommés

sequence_1_0001.jpg  
sequence_1_0002.jpg  
sequence_1_0003.jpg  
...

et fichiers nommés

sequence_1_0001.hmf  
sequence_1_0002.hmf  
sequence_1_0003.hmf  
...

et fichiers nommés

sequence_2_0001.jpg  
sequence_2_0002.jpg  
sequence_2_0003.jpg  
...

et

sequence_2_0001.hmf  
sequence_2_0002.hmf  
sequence_2_0003.hmf  
...

Je veux juste supprimer les fichiers qui commencent par «séquence_1» et se terminent par «.hmf», mais je ne veux pas les supprimer un par un, car il y a des milliers de fichiers. Comment puis-je spécifier à la commande rm que je veux supprimer tout ce qui commence par le préfilx 'séquence_1' et se termine par '.hmf'?

Je travaille actuellement avec un système Linux RedHat, mais j'aimerais savoir comment le faire sur d'autres distributions également.

Paul
la source

Réponses:

28
rm sequence_1*.hmf

supprime les fichiers commençant par sequence_1et se terminant par .hmf.


Globbing est le processus dans lequel votre shell prend un modèle et le développe dans une liste de noms de fichiers correspondant à ce modèle. Ne le confondez pas avec les expressions régulières, ce qui est différent. Si vous passez la plupart de votre temps bash, le Wiki Wooledge a une bonne page sur la globalisation (extension de nom de chemin) . Si vous voulez une portabilité maximale, vous voudrez également lire la spécification POSIX sur la correspondance de modèle .


Dans le cas peu probable où vous rencontrez une erreur "Argument list too long" , vous pouvez jeter un œil à BashFAQ 95 , qui résout ce problème. La solution de contournement la plus simple consiste à décomposer le motif glob en plusieurs morceaux plus petits, jusqu'à ce que l'erreur disparaisse. Dans votre cas, vous pourriez probablement vous en sortir en divisant la correspondance par les chiffres de préfixe 0 à 9, comme suit:

for c in {0..9}; do rm sequence_1_"$c"*.hmf; done
rm sequence_1*.hmf  # catch-all case
jw013
la source
Il s'agit d'un travail très intelligent autour de l'erreur «liste d'arguments trop longue». Dans mon cas, j'ai vingt mille fichiers, donc je suppose que je devrais utiliser une boucle for à partir de 0, .., 20. Droite?
Paul
@Paul Oui, divisez simplement la liste en autant de morceaux que vous le souhaitez, bien qu'à un moment donné, l' findapproche devienne plus facile que de deviner et de vérifier.
jw013
14

Bien que la réponse de jw013 soit correcte par rapport à la globalisation, cette commande peut échouer si vous avez des milliers de correspondances: la ligne de commande développée rm sequence_1_0001.hmf sequence_1_0002.hmf ...générée par le shell peut simplement être trop grande.

Comme Dom l'a suggéré, vous pouvez également utiliser l' -deleteoption avec find:

find . -maxdepth 1 -type f -name 'sequence_1*.hmf' -delete

Les deux -maxdepthet -delete, bien qu'ils ne soient pas dans la norme POSIX, sont assez courants dans les findimplémentations dans la nature. Les distributions Linux utilisent généralement GNU find, qui prend certainement en charge ces options.

Inutile
la source
2
Si vous le pouvez, utilisez l'option -delete pour trouver, il ne se déroule pas pour chaque fichier ...
Dom
Ajouté, bravo. Il semble que cela -deletedevrait être pris en charge sur les systèmes GNU et BSD récents , alors qu'il -print0est uniquement GNU. Il est donc probablement plus portable aussi (bien que cela ne devrait pas faire de différence pour l'OP).
inutile
Au moins OS X trouve -print0, mais il n'est pas inclus dans POSIX.
Lri
5
rm sequence_1_{0000..0999}.hmf
rm sequence_1_{1000..1999}.hmf
rm sequence_1_{2000..2999}.hmf
...

fonctionnerait aussi dans Bash.

Utilisateur inconnu
la source
L'expansion de l'accolade nécessite bash, et la forme zéro rembourrée a besoin de la version 4, je crois.
jw013