Pourquoi les guillemets sont-ils nécessaires pour l'argument des files lors de l'appel de ce script Bash?

Je suis assez nouveau pour les scripts Bash. J'ai un "testcript", que j'ai utilisé comme base pour un script plus avancé / utile:

#!/bin/bash files=$1 for a in $files do echo "$a" done 

Quand j'appelle ceci sans citations, il suffit de choisir un file dans un directory:

 testscript *.txt 

Mais quand je l'appelle avec des citations, il fonctionne correctement et sélectionne tous les files text:

 testscript '*.txt' 

Qu'est-ce qui se passe ici?

Lorsque vous appelez un programme

 testscript *.txt 

alors votre shell effectue l'extension et calcule toutes les valeurs. Ainsi, il pourrait appeler efficacement votre programme comme

 testscript file1.txt file2.txt file3.txt file4.txt 

Maintenant votre programme ne regarde que $1 et ne fonctionne donc que sur file1.txt .

En citant sur la command line, vous passez la string littérale *.txt au script, et c'est ce qui est stocké dans $1 . Votre boucle for élargit ensuite.

Normalement, vous utiliserez "$@" et non pas $1 dans les scripts comme celui-ci.

Ceci est un "gotcha" pour les personnes venant de scripts CMD, où le shell de command ne fait pas de globbing (comme il est connu) et passe toujours la string littérale.

Sans les guillemets, le shell étend *.txt avant d'appeler le script, donc $1 est seulement le premier file qui est développé. Tous les files txt sont des arguments pour votre script à ce stade (en supposant qu'il n'y en a pas trop).

Avec des guillemets, cette string est transmise sans être développée dans le script, ce qui permet ensuite à l'user for faire l'extension, comme vous l'espérez.