Substitution de noms de fichiers

TerminalVoici le cinquième volet de mon cours d’introduction au shell Bash. La dernière fois, nous avons vu en détail la navigation dans les répertoires. Aujourd’hui, nous abordons la substitution de noms de fichiers.

De nombreuses commandes prennent des noms de fichiers en argument. Ces derniers peuvent être cités littéralement ou être spécifiés de manière plus générique. Le shell propose un certain nombre de caractères spéciaux qui permettent de fabriquer des expressions utilisées comme modèles de noms de fichiers.

Le caractère *

Le caractère * représente une suite de caractères quelconques. Pour commencer, créer une série de fichiers.

$ touch f12 f1.i FICa fic.c fic.s monscript.pl MONSCRIPT.pl ours.c

Afficher tous les noms de fichier se terminant par .c.

$ ls *.c
fic.c ours.c

Afficher tous les noms de fichier commençant par la lettre f.

$ ls f*
f12 f1.i fic.c fic.s

Le caractère ?

Le caractère ? représente un caractère quelconque. Là encore, on essaiera d’illustrer par l’exemple.

Afficher tous les noms de fichier ayant une extension composée d’un seul caractère.

$ ls *.?
f1.i fic.c fic.s ours.c

Afficher tous les noms de fichier composés de quatre caractères.

$ ls ????
f1.i FICa

Les crochets [ ]

Les crochets [ ] permettent de spécifier la liste des caractères que l’on attend à une position bien précise dans le nom du fichier. Il est également possible d’utiliser les notions d’intervalle et de négation.

Les exemples cités ci-dessous peuvent produire des résultats surprenants en fonction des variables d’environnement. Le cas échéant, on devra modifier une paire de ces variables.

$ LANG=C
$ LC_COLLATE=C

Pour chacun des exemples, une alternative est donnée qui fonctionne parfaitement pour des variables d’environnement LANG et LC_COLLATE différentes, par exemple fr_FR.utf8.

Fichiers dont le nom commence par f ou o et se termine par le caractère . suivi d’une minuscule.

$ ls [fo]*.[a-z]
f1.i fic.c fic.s ours.c

Alternativement…

$ ls [fo]*.[[:lower:]]
f1.i fic.c fic.s ours.c

Fichiers dont le nom comporte en deuxième caractère une majuscule ou un chiffre ou la lettre i. Les deux premiers caractères seront suivis d’une chaîne quelconque.

$ ls ?[A-Z0-9i]*
FICa MONSCRIPT.pl f1.i f12 fic.c fic.s

Alternativement…

$ ls ?[[:upper:]0-9i]*
f12 f1.i FICa fic.c fic.s MONSCRIPT.pl

Il est également possible d’exprimer la négation de tous les caractères spécifiés à l’intérieur d’une paire de crochets. Ceci se fait en plaçant un ! en première position à l’intérieur de celle-ci.

Noms de fichier ne commençant pas par une minuscule.

$ ls [!a-z]*
FICa MONSCRIPT.pl

Alternativement…

$ ls [![:lower:]]*
FICa MONSCRIPT.pl

Noms de fichier ne commençant pas par une majuscule.

$ ls [!A-Z]*
f1.i f12 fic.c fic.s monscript.pl ours.c

Alternativement…

$ ls [![:upper:]]*
f12 f1.i fic.c fic.s monscript.pl ours.c

Supprimer tous les fichiers dont le nom se termine par .c ou par .s.

$ rm -i *.c *.s
rm : supprimer fichier « fic.c » ? o
rm : supprimer fichier « ours.c » ? o
rm : supprimer fichier « fic.s » ? o

Les fichiers cachés dans la pratique

Un cas spécial mérite d’être mentionné, celui des fichiers cachés. Si l’on applique la substitution des noms de fichiers à cette catégorie de fichiers, on risque d’obtenir des résultats surprenants. Là encore, on va préférer un cas pratique à la théorie.

Créez une série de six fichiers fic1, fic2, fic3, .fic1, .fic2 et .fic3 dans un répertoire vide. Voici la manière la plus rapide de faire ceci.

$ touch {,.}fic{1,2,3}
$ ls -a
.  ..  .fic1  .fic2  .fic3  fic1  fic2  fic3

Si l’on essaie d’afficher uniquement les fichiers cachés à l’aide d’un caractère de substitution, on risque d’être quelque peu surpris par le résultat. Essayez pour voir.

$ ls .*

Au vu de la manière dont le shell traite les caractères de substitution, la séquence .* englobe également le répertoire parent .. qui s’affiche donc de manière apparemment intempestive.

La solution consiste ici à utiliser l’option -d conjointement avec les autres critères.

$ ls -d .*
.  ..  .fic1  .fic2  .fic3
$ ls -d .f*
.fic1  .fic2  .fic3

Une solution alternative consiste à exclure le répertoire parent comme ceci.

$ ls .[!.]*
.fic1  .fic2  .fic3

Documentation

  • Christine Deffaix-Rémy – Programmation shell sous Unix/Linux, pp. 32 – 34
  • Carl Albing – Bash Cookbook, pp. 10 – 12

Lire la suite : Expressions complexes

Ce contenu a été publié dans Bash, Documentation Microlinux, avec comme mot(s)-clé(s) , , . Vous pouvez le mettre en favoris avec ce permalien.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *