Je m'attendais à ne pas obtenir de sortie.
Si nullglob
c'était la valeur par défaut, de nombreuses commandes se comporteraient de manière assez inattendue, car il est (peut-être malheureusement) courant que les commandes traitent le cas de zéro argument de nom de fichier d'une manière qualitativement différente de celle d' un ou plusieurs arguments de nom de fichier.
Supposons que vous ayez activé nullglob
( shopt -s nullglob
) et que vous vous trouviez dans un répertoire où aucun fichier ne correspond *.txt
. Ensuite, il *.txt
s'agira en fait de rien - pas un champ vide, mais pas de champs du tout - comme vous vous y attendiez. Mais cela aurait ces résultats:
ls *.txt
répertorierait tous les fichiers du répertoire actuel (à l'exception des fichiers masqués), car c'est ce qui se ls
produit lorsque vous ne lui passez aucun argument de nom de fichier.
cat *.txt
lirait à partir de l'entrée standard , car lorsqu'il cat
n'a aucun argument de nom de fichier, c'est comme si vous couriez cat -
. S'il s'exécute de manière interactive, il attend en attente d'entrée. De nombreuses commandes se comportent de cette façon.
cp *.txt dest/
échouerait avec l'erreur cp: missing destination file operand after 'dest/'
. Ce n'est pas un désastre, mais c'est déroutant et tout à fait différent du succès silencieux qui est probablement souhaité.
file *.txt
, et divers autres programmes sans comportement spécial dans le cas d'arguments de nom de fichier zéro, échouaient toujours avec un message d'erreur ou d'utilisation quand aucun n'était transmis.
- Même les cas qui se sentent intuitivement comme s'ils devraient travailler ne le feraient pas souvent.
printf 'Got file: "%s"\n' *.txt
imprimerait Got file: ""
au lieu de rien.
- Défaut accidentel de citer les événements de
*
, ?
et [
qui ne sont pas destinés à être élargi par le shell produirait plus souvent des résultats manifestement faux, mais d' une manière qui pourrait être difficile à comprendre. Par exemple, si aucun nom de fichier dans le répertoire courant ne commençait par gedit
, alors apt list gedit*
(où apt list 'gedit*'
c'était prévu) deviendrait juste apt list
et listerait tous les packages disponibles.
Il est donc bon que vous n'obteniez pas ce comportement sans le demander. La situation pratique la plus courante qui est en fait simplifiée nullglob
est probablement for f in *.txt
. Voir aussi cette question (à laquelle la réponse de Sergiy Kolodyazhnyy est liée).
La question la plus difficile à répondre est pourquoi - failglob
où c'est une erreur d'extension d'avoir un glob qui ne correspond à aucun fichier - n'est pas la valeur par défaut dans bash. Je crois que la réponse de Sergiy Kolodyazhnyy saisit la raison de cela même sans y répondre directement. Conserver des globes non expansifs sans produire une erreur d'expansion est (peut-être malheureusement) le comportement standardisé, et c'est aussi un comportement traditionnel, et donc attendu. Bien que bash n'essaie pas d'être entièrement compatible POSIX à moins qu'il ne soit appelé avec le nom sh
ou transmis l' --posix
option, bon nombre de ses choix de conception même lorsqu'il n'est pas en mode POSIX suivent directement POSIX. Ils ont dû choisir un comportement et il y a des inconvénients à aller à l'encontre des attentes des utilisateurs.
Je pense que c'est l'aspect le moins influent historiquement de la question, donc je l'ai gardé pour la fin ... mais il convient de mentionner qu'il y a quelque chose de conceptuellement étrange dans le nullglob
comportement.
nullglob
semble élégant au premier abord parce que, syntaxiquement , il ne traite pas le cas des fichiers correspondant à zéro différemment du cas d'un, deux ou tout autre numéro. Les commandes que nous exécutons, pour lesquelles les globs se développent en arguments, n'ont pas tendance à les traiter de la même manière, comme détaillé ci-dessus. Mais syntaxiquement, cela semble au moins juste, ce qui, à mon avis, est la motivation de votre question.
Et pourtant, il y a une autre incohérence plus subtile qui nullglob
ne résout pas - qu'elle amplifie en fait. Le cas des caractères de globulation zéro ("caractères génériques") est traité différemment de celui d'un, de deux ou de tout autre nombre. Par exemple, avec shopt -s nullglob
, si ab?d?f
ne correspond à aucun fichier, il est supprimé; s'il ab?d
ne correspond à aucun fichier, il est supprimé; mais s'il ab
ne correspond à aucun fichier (c'est-à-dire s'il n'y a pas de fichier dont le nom est exactement ab
), il n'est toujours pas supprimé. Bien sûr, ce serait un désastre s'il était supprimé, car il pourrait ne pas être destiné du tout à faire référence à un fichier existant dans le répertoire courant; il pourrait même ne pas faire référence à un fichier. Mais cela élimine toujours tout espoir de cohérence totale.
Les trois comportements fournis par bash - la valeur par défaut de traiter les globes qui ne correspondent à aucun fichier comme s'ils n'étaient pas des globes et de les transmettre non expansés, le comportement que vous attendiez de les traiter (si vous pardonnez cette étrange tournure de phrase) comme signifiant tout le zéro des fichiers qui correspondent ( nullglob
), et le comportement sûr de les considérer comme des erreurs ( failglob
) - tous représentent des approches différentes de l'ambiguïté inhérente au shell ne pouvant pas savoir si un mot particulier est destiné à être un nom de fichier. Le shell effectue ses extensions sans savoir comment les commandes particulières que vous appelez avec lui traiteront leurs arguments.
C'est l'un des nombreux exemples de séparation des préoccupations . Dans les systèmes dont la conception suit la philosophie Unix, chaque pièce est destinée à faire une chose et à bien la faire . Le shell traite le texte en commandes et arguments et appelle ces commandes, dont la plupart sont externes au shell lui-même. Cela a tendance à être beaucoup plus agréable et plus polyvalent que les systèmes où les commandes externes sont elles - mêmes responsables de l'exécution de ces transformations (comme avec les processeurs de commandes traditionnels sous DOS et Windows). Mais il a ses inconvénients occasionnels.
shopt -s nullglob
produira des chaînes vides pour des modèles inégalés etshopt -u nullglob
(réglage standard) produira le modèle lui-même.