L’ nullglob
option (BTW étant une zsh
invention ajoutée seulement des années plus tard à bash
( 2.0
)) ne serait pas idéale dans un certain nombre de cas. Et ls
est un bon exemple:
ls *.txt
Ou son équivalent plus correct:
ls -- *.txt
Avec nullglob
on serait exécuté ls
sans argument considéré comme ls -- .
(liste le répertoire en cours) si aucun fichier ne correspond, ce qui est probablement pire que d'appeler ls
avec un littéral *.txt
comme argument.
Vous auriez des problèmes similaires avec la plupart des utilitaires de texte:
grep foo *.txt
Chercherais foo
sur stdin s'il n'y a pas de txt
fichier.
Un choix plus judicieux, et celui de csh, tcsh, zsh ou fish 2.3+ (et des premiers shells Unix) consiste à annuler la commande si le glob ne correspond pas.
bash
(depuis la version 3) a une failglob
option pour cela (intéressant pour cette discussion, car contrairement à ash
AT & T ksh
ou zsh
, bash
ne supporte pas les étendues locales pour les options (bien que cela change dans la version 4.4), cette option, lorsqu'elle est activée globalement, casse quelques problèmes comme les fonctions d'achèvement de bash).
Notez que csh et tcsh sont légèrement différentes de zsh
, fish
ou bash -O failglob
dans des cas comme:
ls -- *.txt *.html
Où vous avez besoin que tous les globs ne correspondent pas pour que la commande soit annulée. Par exemple, s'il existe un fichier txt et aucun fichier html, cela devient:
ls -- file.txt
Vous pouvez obtenir ce comportement avec zsh
avec setopt cshnullglob
bien d' une manière plus raisonnable de le faire en zsh
serait d'utiliser un glob comme:
ls -- *.(txt|html)
Dans zsh
et ksh93
, vous pouvez également appliquer nullglob sur une base globale, ce qui est une approche beaucoup plus saine que de modifier un paramètre global:
files=(*.txt(N)) # zsh
files=(~(N)*.txt) # ksh93
créerait un tableau vide s'il n'y avait pas de txt
fichier au lieu d'échouer la commande avec une erreur (ou d'en faire un tableau avec un *.txt
argument littéral avec d'autres shells).
Les versions fish
antérieures à 2.3 fonctionneraient de la même façon, bash -O nullglob
mais donneraient un avertissement lorsqu'elles sont interactives lorsqu'un glob n'a pas de correspondance Depuis la version 2.3, cela fonctionne comme zsh
sauf pour les globs utilisés dans for
, set
ou count
.
Sur la note d’histoire, le comportement a en fait été interrompu par le shell Bourne. Dans les versions précédentes d'Unix, la globulation était effectuée via l' /etc/glob
assistant et ce dernier se comportait comme suit csh
: la commande échouerait si aucun des globs ne correspondait à un fichier et supprimait les globs sans correspondance sinon.
La situation dans laquelle nous nous trouvons aujourd’hui est donc due à une mauvaise décision prise dans le shell Bourne.
Notez que le shell Bourne (et le shell C) est accompagné d’une autre nouvelle fonctionnalité Unix: l’environnement. Cette expansion signifiait variable (son prédécesseur avait seulement les $1
, $2
... les paramètres de position). Le shell Bourne a également introduit la substitution de commande.
Une autre décision d' une mauvaise conception de la coque Bourne était de réaliser globbing (et le fractionnement) lors de l'expansion des variables et la substitution de commande (éventuellement pour une compatibilité descendante avec la coque Thompson où echo $1
invoquerais encore /etc/glob
si les $1
caractères génériques contenus (il a été plus comme extension macro pré-processeur là, comme dans la valeur développée a été analysé à nouveau comme un code shell)).
Des globs défaillants qui ne correspondent pas signifieraient par exemple que:
pattern='a.*b'
grep $pattern file
échouerait la commande (à moins que certains a.whateverb
fichiers ne se trouvent dans le répertoire en cours). csh
Dans ce cas, la commande échoue (et je dirais que c'est mieux que de laisser un bogue en sommeil ici, même s'il n'est pas aussi bon que de ne pas faire de globing du tout comme dans zsh
).