Dans la plupart des coquilles, ce nullglob
n'est pas la valeur par défaut. Cela signifie, par exemple, si vous exécutez cette commande
ls *
dans un répertoire vide, le *
glob sera étendu à un littéral *
, à une liste d'arguments vide. Il existe des moyens de modifier ce comportement afin que, *
dans un répertoire vide, une liste d'arguments vide soit retournée, ce qui semblerait plus intuitif.
Alors, y a-t-il une raison pour laquelle il nullglob
est désactivé par défaut? Si oui, quelle est cette raison?
*
s'agit d'un glob et s'étend à tous les fichiers existants ; comment est-il "intuitif" pour qu'il y ait un cas particulier où les globs de répertoire vides sont "étendus" à un littéral*
?Réponses:
L’
nullglob
option (BTW étant unezsh
invention ajoutée seulement des années plus tard àbash
(2.0
)) ne serait pas idéale dans un certain nombre de cas. Etls
est un bon exemple:Ou son équivalent plus correct:
Avec
nullglob
on serait exécutéls
sans argument considéré commels -- .
(liste le répertoire en cours) si aucun fichier ne correspond, ce qui est probablement pire que d'appelerls
avec un littéral*.txt
comme argument.Vous auriez des problèmes similaires avec la plupart des utilitaires de texte:
Chercherais
foo
sur stdin s'il n'y a pas detxt
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 unefailglob
option pour cela (intéressant pour cette discussion, car contrairement àash
AT & Tksh
ouzsh
,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
oubash -O failglob
dans des cas comme: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:
Vous pouvez obtenir ce comportement avec
zsh
avecsetopt cshnullglob
bien d' une manière plus raisonnable de le faire enzsh
serait d'utiliser un glob comme:Dans
zsh
etksh93
, vous pouvez également appliquer nullglob sur une base globale, ce qui est une approche beaucoup plus saine que de modifier un paramètre global: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 commezsh
sauf pour les globs utilisés dansfor
,set
oucount
.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 suitcsh
: 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:
é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 danszsh
).la source
nullglob
semble rompre l’achèvement de la tabulation (appuyer sur la touche de tabulation ne fait rien quand il est activé).files=$(shopt -s nullglob;echo *.txt)
xpg_echo
) en variables scalaires . Vous aurez besoin de quelque chose commereadarray -td '' files < <(shopt -s nullglob; printf '%s\0' *.txt)
avecbash
4.4 ou plus ou(shopt -s nullglob; printf '%s\0' *.txt) | xargs -r0 cmd
avec GNUxargs
pour que cela soit utilisable avec des noms de fichiers arbitraires. Ou, toujours avec bash4.4, utilisez une fonction d'assistance qui utiliselocal -
(copiée à partir de cendres 25 ans plus tard) un champ local pour les options.