GNU/Linux >> Tutoriels Linux >  >> Linux

Pourquoi Nullglob n'est-il pas par défaut ?

Dans la plupart des shells 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, il développera le * glob en un * littéral , à la place d'une liste vide d'arguments. Il existe des moyens de modifier ce comportement, de sorte que * dans un répertoire vide renverra une liste vide d'arguments, ce qui semblerait plus intuitif.

Alors, y a-t-il une raison pour laquelle nullglob est désactivé par défaut ? Si oui, quelle est cette raison ?

Réponse acceptée :

Le nullglob option (dont BTW est un zsh invention, ajoutée seulement des années plus tard à bash (2.0 )) ne serait pas idéal dans un certain nombre de cas. Et ls est un bon exemple :

ls *.txt

Ou son équivalent plus correct :

ls -- *.txt

Avec nullglob on exécuterait ls sans argument qui est traité comme ls -- . (liste le répertoire courant) si aucun fichier ne correspond, ce qui est probablement pire que d'appeler ls avec un *.txt littéral comme argument.

Vous auriez des problèmes similaires avec la plupart des utilitaires de texte :

grep foo *.txt

Rechercherait foo sur stdin s'il n'y a pas de txt fichier.

Une valeur par défaut plus raisonnable, et celle de csh, tcsh, zsh ou fish 2.3+ (et des premiers shells Unix) est d'annuler complètement la commande si le glob ne correspond pas.

bash (depuis la version 3) a un failglob option pour cela (intéressant pour cette discussion, car contrairement à ash , AT&T ksh ou zsh , bash ne prend pas en charge les étendues locales pour les options (bien que cela doive changer dans 4.4), cette option, lorsqu'elle est activée globalement, casse certaines choses comme les fonctions bash-completion).

Notez que csh et tcsh sont légèrement différents 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 y a un fichier txt et aucun fichier html, cela devient :

ls -- file.txt

Vous pouvez obtenir ce comportement avec zsh avec setopt cshnullglob bien qu'une manière plus sensée de le faire en zsh serait d'utiliser un glob comme :

ls -- *.(txt|html)

En zsh et ksh93 , vous pouvez également appliquer nullglob sur une base globale, ce qui est une approche beaucoup plus sensée que la modification d'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).

Versions de fish avant 2.3 fonctionnerait comme bash -O nullglob mais donner un avertissement lorsqu'il est interactif lorsqu'un glob n'a pas de correspondance. Depuis la 2.3, cela fonctionne comme zsh sauf pour les globs utilisés dans for , set ou count .

Maintenant, sur la note d'historique, le comportement était en fait cassé par l'obus Bourne. Dans les versions précédentes d'Unix, le globbing se faisait via le /etc/glob helper et que helper s'est comporté comme csh  :il échouerait la commande si aucun des globs ne correspondait à aucun fichier et supprimerait les globs sans correspondance sinon.

Connexe :Bash + comment quitter le script secondaire et le script principal à la fois ?

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 venu avec une autre nouvelle fonctionnalité Unix :l'environnement. Cela signifiait une expansion variable (son prédécesseur n'avait que le $1 , $2 … paramètres de position). Le shell Bourne a également introduit la substitution de commandes.

Une autre mauvaise décision de conception du shell Bourne était d'effectuer le globbing (et le fractionnement) lors de l'expansion des variables et de la substitution de commandes (éventuellement pour une compatibilité descendante avec le shell Thompson où echo $1 invoquerait toujours /etc/glob si $1 contenait des caractères génériques (cela ressemblait plus à une extension de macro de préprocesseur, car la valeur étendue était à nouveau analysée en tant que code shell)).

Des globs défaillants qui ne correspondent pas signifieraient par exemple que :

pattern='a.*b'
grep $pattern file

échouerait la commande (sauf s'il y a des a.whateverb fichiers dans le répertoire courant). csh (qui effectue également le globbing lors de l'expansion des variables) échoue la commande dans ce cas (et je dirais que c'est mieux que de laisser un bogue dormant là-bas, même si ce n'est pas aussi bon que de ne pas faire de globbing du tout comme dans zsh ).


Linux
  1. Pourquoi le CD n'est-il pas un programme ?

  2. Linux - Pourquoi utilisons-nous Su - Et pas seulement Su ?

  3. Pourquoi Find n'accepte-t-il pas '-exec Cp {} Dir +' ?

  4. Pourquoi `exit &` ne fonctionne pas ?

  5. Pourquoi Lpd n'est-il pas activé par défaut dans la transmission ?

Pourquoi "effacer" ne pas effacer tout l'écran ?

Le script user-data (cloud-init) ne s'exécute pas sur EC2

pourquoi sftp rmdir ne fonctionne-t-il pas?

Pourquoi utilisons-nous su - et pas seulement su ?

Fedora 25 n'utilise PAS wayland par défaut !

Pourquoi ne pas bloquer ICMP ?