Dans tous les shells que je connais, rm [A-Z]*
supprime tous les fichiers commençant par une lettre majuscule, mais avec bash, cela supprime tous les fichiers commençant par une lettre.
Comme ce problème existe sur Linux et Solaris avec bash-3 et bash-4, il ne peut pas s'agir d'un bogue causé par un comparateur de modèle bogué dans la libc ou une définition de paramètres régionaux mal configurée.
Ce comportement étrange et risqué est-il intentionnel ou s'agit-il simplement d'un bug non corrigé depuis de nombreuses années ?
Réponse acceptée :
Notez que lors de l'utilisation d'expressions de plage telles que [a-z], des lettres de l'autre casse peuvent être incluses, selon le paramètre de LC_COLLATE.
LC_COLLATE
est une variable qui détermine l'ordre de classement utilisé lors du tri des résultats de l'expansion des noms de chemin et détermine le comportement des expressions de plage, des classes d'équivalence et des séquences d'assemblage dans l'expansion des noms de chemin et la correspondance des modèles.
Considérez ce qui suit :
$ touch a A b B c C x X y Y z Z
$ ls
a A b B c C x X y Y z Z
$ echo [a-z] # Note the missing uppercase "Z"
a A b B c C x X y Y z
$ echo [A-Z] # Note the missing lowercase "a"
A b B c C x X y Y z Z
Remarquez quand la commande echo [a-z]
est appelée, la sortie attendue serait tous les fichiers avec des caractères minuscules. Aussi, avec echo [A-Z]
, des fichiers avec des caractères majuscules seraient attendus.
Classements standard avec des paramètres régionaux tels que en_US
avoir l'ordre suivant :
aAbBcC...xXyYzZ
- Entre
a
etz
(en[a-z]
) sont TOUTES des lettres majuscules, à l'exception deZ
. - Entre
A
etZ
(en[A-Z]
) sont TOUTES des lettres minuscules, à l'exception dea
.
Voir :
aAbBcC[...]xXyYzZ
| |
from a to z
aAbBcC[...]xXyYzZ
| |
from A to Z
Si vous modifiez le LC_COLLATE
variable en C
il ressemble à ce que nous attendions :
$ export LC_COLLATE=C
$ echo [a-z]
a b c x y z
$ echo [A-Z]
A B C X Y Z
Donc, ce n'est pas un bug , c'est un problème de classement .
Au lieu d'expressions de plage, vous pouvez utiliser des classes de caractères définies par POSIX, telles que upper
ou lower
. Ils fonctionnent également avec différents LC_COLLATE
configurations et même avec des caractères accentués :
$ echo [[:lower:]]
a b c x y z à è é
$ echo [[:upper:]]
A B C X Y Z