Petit precis de shell » Historique » Version 55
Julien Enselme, 02/08/2014 20:31
Parser des arguments
1 | 30 | Julien Enselme | Le shell est un langage assez particulier qu'on ne connait pas forcément en arrivant à centrale et qu'on a pas forcément l'occasion de beaucoup pratiquer. Le but de ce document est de rappeler les quelques bases du langage, de rappeller les différences notables avec bash et de fournir quelques [[Shell secours|solutions standard]] à des problèmes courants afin que le nouveau membre du club Drupal ne soit pas désemparé et puisse comprendre les scripts. Il ne se veut en aucun cas un cours/tuto complet et exhaustif. Des bases de shell et d'un autre langage de programation peut s'avérer utile. "Voir le site du zéros":http://www.siteduzero.com/informatique/tutoriels/reprenez-le-controle-a-l-aide-de-linux pour un tuto orienté vers les débutants. |
---|---|---|---|
2 | 14 | Julien Enselme | |
3 | 49 | Julien Enselme | {{>toc}} |
4 | 1 | Julien Enselme | |
5 | 3 | Julien Enselme | h1. Quelques rappels d'Unix |
6 | 3 | Julien Enselme | |
7 | 3 | Julien Enselme | Le langage shell est le langage de script qui vient par défaut avec _tous_ les Unix. En effet, même si désormais d'autres interpréteurs plus modernes sont désormais répandus (bash, csh, zsh, etc.), ils ont tous conservé la compatibilité avec le shell. |
8 | 3 | Julien Enselme | |
9 | 3 | Julien Enselme | Comme pour la plupart des langages de script, il existe deux façons d'exécuter des instructions shell : |
10 | 3 | Julien Enselme | |
11 | 3 | Julien Enselme | * directement dans l'interpréteur |
12 | 3 | Julien Enselme | * dans un script shell |
13 | 3 | Julien Enselme | |
14 | 31 | Julien Enselme | Pour lancer un interpréteur shell, rien de plus simple : lancer un terminal (graphique ou tty). Et oui, le shell comprend toutes les commandes Unix que vous avez vues en début d'année (pwd, cd, cp). Vous pouvez donc les réutiliser _telles quelles_ dans vos scripts et utiliser un simple terminal pour faire des boucles, des conditions et j'en passe. |
15 | 3 | Julien Enselme | |
16 | 1 | Julien Enselme | h1. Les bases du shell |
17 | 3 | Julien Enselme | |
18 | 4 | Julien Enselme | Il est très important de comprendre et de garder à l'esprit qu'en shell tout est : |
19 | 4 | Julien Enselme | |
20 | 4 | Julien Enselme | * chaîne de caractères (y compris les nombres) ! Entrez @echo 1 + 1@ dans le terminal pour vous en convaincre. |
21 | 4 | Julien Enselme | * commande et que donc elles peuvent prendre des arguments (cela s'éclaircira plus tard) |
22 | 4 | Julien Enselme | |
23 | 4 | Julien Enselme | h2. Syntaxe de base |
24 | 4 | Julien Enselme | |
25 | 4 | Julien Enselme | Les commandes s'écrivent soit : |
26 | 4 | Julien Enselme | |
27 | 6 | Florent Torregrosa | * les unes à la suite des autres séparées par ; (peu recommandé) |
28 | 4 | Julien Enselme | * séparées les unes des autres par un saut de ligne |
29 | 4 | Julien Enselme | |
30 | 32 | Julien Enselme | Chaque commande peut prendre des options (qui modifient la façon dont la commande se comporte : affiche de l'aide, beaucoup d'information, etc.) de deux types : |
31 | 4 | Julien Enselme | |
32 | 32 | Julien Enselme | * les options courtes (l, r, h pour @ls@ par exemple) qui sont passés comme suit : @CMD -ARG@ |
33 | 32 | Julien Enselme | * les options longues (recursive pour @rsync@ par exemple) qui se passent comme ceci : @CMD --ARGUMENT@ |
34 | 4 | Julien Enselme | |
35 | 32 | Julien Enselme | Il est évidement possible de passer plusieurs options à une même commande. |
36 | 1 | Julien Enselme | |
37 | 32 | Julien Enselme | {{tip(Certains paramètres existent sous une forme courte et une forme longue. Consulter le manuel de la commande pour plus de détails. Le manuel contient également la liste complète des arguments supportés par une commande.)}} |
38 | 1 | Julien Enselme | |
39 | 1 | Julien Enselme | {{note(Certains commandes ne respectent pas la convention énoncée ce-dessus. Leurs arguments long se passent avec un seul - (find en est un exemple))}} |
40 | 32 | Julien Enselme | |
41 | 32 | Julien Enselme | Les commandes peuvent aussi prendre des arguments qui permettent de savoir comment s'exécuter. Ils se placent après les paramètres. |
42 | 32 | Julien Enselme | |
43 | 32 | Julien Enselme | Exemple : @ls -R ~/Documents@. Par défaut, @ls@ ne liste que les fichiers et dossiers dans le dossier courant. L'option @-R@ permet de descendre dans tous les dossiers. L'argument "~/Documents" permet d'exécuter la commande dans le dossier ~/Documents sans s'y déplacer. |
44 | 32 | Julien Enselme | |
45 | 32 | Julien Enselme | {{tip(Pensez à la commande man qui prend comme argument une autre commande et affiche son manuel)}} |
46 | 4 | Julien Enselme | |
47 | 33 | Julien Enselme | h2. Valeurs de retour des commandes et exceptions |
48 | 5 | Julien Enselme | |
49 | 43 | Julien Enselme | Une fois qu'une commande s'est exécutée, elle renvoie une valeur de retour afin "d'informer" l'utilisateur. Cette valeur permet en effet de savoir si la commande s'est exécutée correctement. Voici les valeurs de retour courantes possibles et leur signification : |
50 | 5 | Julien Enselme | |
51 | 5 | Julien Enselme | * 0 : tout va bien |
52 | 5 | Julien Enselme | * 1 : erreur |
53 | 5 | Julien Enselme | * 2 : erreur grave |
54 | 5 | Julien Enselme | |
55 | 6 | Florent Torregrosa | Vous pouvez vous aussi utiliser ces valeurs de retour. Par défaut, un script qui se complète correctement retourne 0. Mais vous pouvez (par exemple si un utilisateur tente d'exécuter un script qui nécessite un argument sans) retourner un autre code d'erreur avec la commande @exit@. Il suffit de lui passer le code qu'elle doit retourner. Votre script s'arrêtera alors avec le code d'erreur spécifié. |
56 | 5 | Julien Enselme | |
57 | 46 | Julien Enselme | Vous pouvez connaître la valeur de retour de la dernière commande exécutée avec la variable @$?@. |
58 | 46 | Julien Enselme | |
59 | 13 | Julien Enselme | h2. Exécuter une commande |
60 | 13 | Julien Enselme | |
61 | 13 | Julien Enselme | S’il est facile dans les cas simples d’exécuter une commande, dès lors qu’en shell tout est chaîne de caractères, si vous voulez affecter la sortie d’une commande à une variable, vous ne pouvez pas simplement faire @var=CMD@ car var va alors valoir la chaîne CMD. |
62 | 13 | Julien Enselme | |
63 | 13 | Julien Enselme | Pour obtenir le résultat souhaité vous devez placer CMS entre backquote `` ou entre $(…). Par exemple : @var=`ls`@ ou @var=$(ls)@. |
64 | 13 | Julien Enselme | |
65 | 13 | Julien Enselme | La syntaxe `` serait plus ancienne et supportée partout. La syntaxe $(…) serait plus récente et présente l’avantage de pouvoir imbriquer les commandes sans ambiguïté. |
66 | 13 | Julien Enselme | |
67 | 4 | Julien Enselme | h2. Conditions et itérations |
68 | 7 | Julien Enselme | |
69 | 11 | Julien Enselme | h3. Conditions if … else … |
70 | 7 | Julien Enselme | |
71 | 7 | Julien Enselme | La structure générale d'une condition est la suivante : |
72 | 7 | Julien Enselme | |
73 | 7 | Julien Enselme | <pre> |
74 | 7 | Julien Enselme | <code> |
75 | 7 | Julien Enselme | if QQC |
76 | 7 | Julien Enselme | then |
77 | 7 | Julien Enselme | CMDS |
78 | 7 | Julien Enselme | else |
79 | 7 | Julien Enselme | CMDS |
80 | 7 | Julien Enselme | fi |
81 | 7 | Julien Enselme | </code> |
82 | 7 | Julien Enselme | </pre> |
83 | 7 | Julien Enselme | |
84 | 44 | Julien Enselme | Le @else@ est facultatif. Il est aussi possible de regrouper @if@ et @then@ en une seule ligne comme ceci : @if QQC ; then@. On peut également utiliser des @elif@. |
85 | 7 | Julien Enselme | |
86 | 7 | Julien Enselme | La question que vous devriez avoir est que mettre à la place de @QQC@. Il y a deux possibilités : |
87 | 7 | Julien Enselme | |
88 | 7 | Julien Enselme | * la fonction @test@ |
89 | 7 | Julien Enselme | * une commande |
90 | 7 | Julien Enselme | |
91 | 11 | Julien Enselme | h4. La fonction test |
92 | 7 | Julien Enselme | |
93 | 7 | Julien Enselme | {{important(Dans toute la suite, il faudra faire très *attention aux espaces*)}} |
94 | 7 | Julien Enselme | |
95 | 34 | Julien Enselme | La fonction @test@ s'utilise en général comme suit : @if [ ARGS ]@ *Notez les espaces !* |
96 | 7 | Julien Enselme | |
97 | 7 | Julien Enselme | *IMPORTANT* : La syntaxe *@if [[ ARGS ]]@* n'est valide qu'avec *bash*. Voir [[Petit_precis_de_shell#Différences notables avec bash|Différences notables avec bash]] |
98 | 7 | Julien Enselme | |
99 | 34 | Julien Enselme | Pour faire un test, il suffit ensuite de passer les bons arguments à la commande. Par exemple, pour tester si une chaîne est vide : @if [ -z $chaine ]@. Si l’argument a besoin de deux paramètres pour fonctionner, mettre un paramètre de chaque côté de celui-ci. Par exemple, pour faire un test d’égalité de chaîne de caractères : @CHAINE1 = CHAINE2@. |
100 | 10 | Julien Enselme | |
101 | 10 | Julien Enselme | On peut aussi combiner les arguments avec des ET et des OU avec les options @-a@ et @-o@. Le caractère "!" permet de faire une négation. |
102 | 10 | Julien Enselme | |
103 | 41 | Julien Enselme | {{tip(On peut également faire des ET avec && et des OU avec ||. Ces opérateurs ne sont pas spécifiques à la fonction test, ils font parti du langage. Il est donc tout à fait possible de les utiliser [[Petit_precis_de_shell#ET-et-OU-dans-le-langage|sans la fonction test]].)}} |
104 | 41 | Julien Enselme | |
105 | 10 | Julien Enselme | Voir ci-dessous pour la liste complète. |
106 | 10 | Julien Enselme | |
107 | 10 | Julien Enselme | {{important(En shell, tout est chaîne de caractère. Bien faire attention au type que l’on veut tester (chaîne ou nombre))}} |
108 | 10 | Julien Enselme | |
109 | 21 | Julien Enselme | *Tests sur les chaînes de caractères* |
110 | 21 | Julien Enselme | |
111 | 10 | Julien Enselme | |_. Argument |_. Signification | |
112 | 10 | Julien Enselme | | = | égalité | |
113 | 1 | Julien Enselme | | -z | chaîne vide | |
114 | 1 | Julien Enselme | | -n | chaîne non vide | |
115 | 21 | Julien Enselme | |
116 | 47 | Julien Enselme | {{Important(Lors des tests de chaîne de caractères, entourez la variable de guillemets. Sinon, si la chaîne est vide, le test ne pourra être effectué)}} |
117 | 47 | Julien Enselme | |
118 | 21 | Julien Enselme | *Tests sur les nombres* |
119 | 21 | Julien Enselme | |
120 | 10 | Julien Enselme | |_. Argument |_. Signification | |
121 | 10 | Julien Enselme | | -eq | égalité | |
122 | 34 | Julien Enselme | | -ne | différent | |
123 | 10 | Julien Enselme | | -lt | strictement plus petit | |
124 | 10 | Julien Enselme | | -gt | strictement plus grand | |
125 | 10 | Julien Enselme | | -ge | plus grand ou égal | |
126 | 10 | Julien Enselme | | -le | plus petit ou égal | |
127 | 10 | Julien Enselme | |
128 | 7 | Julien Enselme | h4. Test avec une commande |
129 | 1 | Julien Enselme | |
130 | 35 | Julien Enselme | Comme indiqué précédemment, une commande qui s’exécute correctement est considérée comme vraie. Ainsi, il est tout a fait possible, par exemple, pour savoir si on arrive à se connecter à un serveur mysql de faire simplement : @if mysql -h HOST -u asso -pTATA@. |
131 | 10 | Julien Enselme | |
132 | 10 | Julien Enselme | {{tip(Parfois vous pourrez rencontrer des problèmes. Pensez alors à donner cette commande en argument à la fonction test)}} |
133 | 7 | Julien Enselme | |
134 | 54 | Julien Enselme | {{tip(Le shell contient deux fonctions utiles: _true_ et _false_. La première renvoie toujours 0 et la seconde toujours 1. Vous pouvez les trouver utiles si vous avez besoin de manipuler des booléens.)}} |
135 | 54 | Julien Enselme | |
136 | 12 | Julien Enselme | h3. Boucles while/until |
137 | 12 | Julien Enselme | |
138 | 12 | Julien Enselme | La structure générale est la suivante : |
139 | 12 | Julien Enselme | <pre> |
140 | 12 | Julien Enselme | while QQC |
141 | 12 | Julien Enselme | do |
142 | 12 | Julien Enselme | CMD |
143 | 12 | Julien Enselme | done |
144 | 12 | Julien Enselme | </pre> |
145 | 12 | Julien Enselme | |
146 | 12 | Julien Enselme | Il est possible de regrouper @while QQC@ et le @do@ en @while QQC ; do@. Le QQC peut être remplacer par exactement les mêmes choses que pour la condition. Se référer à cette section pour les précisions. |
147 | 12 | Julien Enselme | |
148 | 12 | Julien Enselme | Le shell propose également le mot clé @until QQC@ qui fait une action jusqu’à ce que QQC soit réalisé. |
149 | 12 | Julien Enselme | |
150 | 12 | Julien Enselme | h3. Boucle for |
151 | 12 | Julien Enselme | |
152 | 12 | Julien Enselme | L’utilisation de la boucle for en shell ressemble à celle de python. La structure générale est la suivante : |
153 | 12 | Julien Enselme | <pre> |
154 | 12 | Julien Enselme | for var in `CMD` |
155 | 12 | Julien Enselme | do |
156 | 12 | Julien Enselme | CMD |
157 | 12 | Julien Enselme | done |
158 | 12 | Julien Enselme | </pre> |
159 | 12 | Julien Enselme | |
160 | 12 | Julien Enselme | La variable _var_ va alors prendre une à une les valeurs données par CMD. Par exemple, @for file in `ls`@ la variable var va prendre tour à tour le nom de tous les fichiers et dossiers donnés par la commande @ls@. |
161 | 12 | Julien Enselme | |
162 | 23 | Julien Enselme | Vous pouvez également utiliser for pour boucler d’un nombre à un autre avec la syntaxe : @for i in `seq [first [incr]] last`@ |
163 | 16 | Julien Enselme | |
164 | 18 | Julien Enselme | h1. Paramètres de scripts |
165 | 18 | Julien Enselme | |
166 | 18 | Julien Enselme | h2. Généralités |
167 | 18 | Julien Enselme | |
168 | 18 | Julien Enselme | Un script peut prendre des paramètres qui ont le même but que les arguments d'une fonction : lui passer des informations. Un paramètre peut être : |
169 | 18 | Julien Enselme | |
170 | 18 | Julien Enselme | * une variable |
171 | 18 | Julien Enselme | * une chaîne de caractère (donc un nombre, en shell on ne fait pas la distinction). Si la chaîne à passer en paramètre contient plusieurs mots séparés par des espaces, ne pas oublier de la mettre entre ' ou ". |
172 | 18 | Julien Enselme | |
173 | 36 | Julien Enselme | {{tip(Si une varaible coucou contient la chaîne 'salut', alors '$coucou toi' sera compris _$coucou toi_ tandis que "$coucou toi" sera interprétée en _salut toi_)}} |
174 | 18 | Julien Enselme | |
175 | 18 | Julien Enselme | Les paramètres se passent à un script comme ceux d'une commande. Ils sont ensuite disponibles dans l'ordre avec des numéros : |
176 | 18 | Julien Enselme | |
177 | 18 | Julien Enselme | * le premier : $1 |
178 | 18 | Julien Enselme | * le deuxième : $2 |
179 | 18 | Julien Enselme | * et ainsi de suite |
180 | 18 | Julien Enselme | |
181 | 18 | Julien Enselme | {{important(Le shell ne supporte *que* 9 paramètres)}} |
182 | 18 | Julien Enselme | |
183 | 18 | Julien Enselme | h2. Les paramètres spéciaux |
184 | 18 | Julien Enselme | |
185 | 18 | Julien Enselme | * $0 : contient le nom du script |
186 | 18 | Julien Enselme | * $# : contient le nombre d'arguments passés au script |
187 | 36 | Julien Enselme | {{important(Le paramète $0 est toujours passé au script. $# est donc toujours supérieur ou égal à 1)}} |
188 | 18 | Julien Enselme | * $? : le code de retour de la dernière commande invoquée |
189 | 18 | Julien Enselme | * $$ : le PID du shell qui exécute le script |
190 | 1 | Julien Enselme | * $! : le PID du dernier processus lancé en arrière plan |
191 | 25 | Julien Enselme | * $* : l'ensemble des paramètres en un seul argument |
192 | 25 | Julien Enselme | * $@ : L'ensemble des arguments, un argument par paramètre |
193 | 25 | Julien Enselme | |
194 | 36 | Julien Enselme | Pour bien voir la différence entre $* et $@, il suffit de regarder la sortie du script suivant : |
195 | 25 | Julien Enselme | <pre> |
196 | 25 | Julien Enselme | <code class="bash"> |
197 | 25 | Julien Enselme | echo 'Avec $*' |
198 | 25 | Julien Enselme | for param in "$*" ; do |
199 | 25 | Julien Enselme | echo $param |
200 | 25 | Julien Enselme | done |
201 | 25 | Julien Enselme | |
202 | 25 | Julien Enselme | echo 'Avec $@' |
203 | 25 | Julien Enselme | for param in "$@" ; do |
204 | 25 | Julien Enselme | echo $param |
205 | 25 | Julien Enselme | done |
206 | 25 | Julien Enselme | </code> |
207 | 25 | Julien Enselme | </pre> |
208 | 18 | Julien Enselme | |
209 | 18 | Julien Enselme | h2. Les commandes shift et set |
210 | 18 | Julien Enselme | |
211 | 18 | Julien Enselme | La commande @set@ permet d'affecter les paramètres. Ainsi @set bonjour salut bonsoir@ va initialiser $1 à bonjour, $2 à salut et $3 à bonsoir. Les paramètres spéciaux $#, $* et $@ sont mis à jour. |
212 | 18 | Julien Enselme | |
213 | 36 | Julien Enselme | La commande @shift@ permet de décaler les variables. Ainsi, si après @shift@ $1 prend la valeur de $2 et ainsi de suite. @shift n@ décale les arguments de n. |
214 | 18 | Julien Enselme | |
215 | 17 | Julien Enselme | h1. Les fonctions |
216 | 17 | Julien Enselme | |
217 | 17 | Julien Enselme | Il est tout à fait possible de définir en shell des fonctions que ce soit dans un script ou un terminal. La syntaxe est la même. |
218 | 17 | Julien Enselme | |
219 | 17 | Julien Enselme | <pre> |
220 | 39 | Julien Enselme | nom_de_la-fonction () { |
221 | 17 | Julien Enselme | CMDS |
222 | 17 | Julien Enselme | } |
223 | 17 | Julien Enselme | </pre> |
224 | 1 | Julien Enselme | |
225 | 39 | Julien Enselme | ou encore |
226 | 39 | Julien Enselme | |
227 | 39 | Julien Enselme | <pre> |
228 | 39 | Julien Enselme | function nom_de_la-fonction { |
229 | 39 | Julien Enselme | CMDS |
230 | 39 | Julien Enselme | } |
231 | 39 | Julien Enselme | </pre> |
232 | 39 | Julien Enselme | |
233 | 1 | Julien Enselme | Les fonctions ainsi créées s'utilisent comme les commandes classiques et leurs arguments se manipulent exactement comme ceux d'un script. Voir [[Petit_precis_de_shell##Paramètres-de-scripts|la section dédiée]]. Il faut néanmoins faire attention à deux points : |
234 | 17 | Julien Enselme | |
235 | 39 | Julien Enselme | * la portée des variables |
236 | 17 | Julien Enselme | * la valeur de retour |
237 | 17 | Julien Enselme | |
238 | 39 | Julien Enselme | Par défaut, les variables définies dans la fonction resteront accessibles une fois la fonction exécutée. De même les varables définies auparavant restent acessibles dans la fonction. *Ces varaibles sont donc globales par défaut.* Pour qu'une variable soit locale, il faut utiliser le mot clé @local@ lors de sa définition. Par exemple : @local nom=clubdrupal@ (NB : local est une commande qui peut prendre des options). |
239 | 17 | Julien Enselme | |
240 | 37 | Julien Enselme | Pour qu'une fonction en bash retourne une valeur comme vous pouvez en avoir l'habitude dans d'autres langages, il faut utiliser la commande @echo@. En effet, il n'existe pas d'instruction @return@ puisque par défaut les variables sont globales. Il faut alors faire très attention. Par exemple avec la fonction suivante : |
241 | 17 | Julien Enselme | |
242 | 17 | Julien Enselme | <pre> |
243 | 17 | Julien Enselme | <code class="bash"> |
244 | 17 | Julien Enselme | x_files () { |
245 | 17 | Julien Enselme | top_secret=`dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -f1 -d" "` |
246 | 17 | Julien Enselme | echo $top_secret |
247 | 8 | Julien Enselme | } |
248 | 8 | Julien Enselme | </code> |
249 | 8 | Julien Enselme | </pre> |
250 | 9 | Julien Enselme | |
251 | 9 | Julien Enselme | * Si on fait @x_files@ on affiche à l'écran le contenu de @$top_secret@ |
252 | 9 | Julien Enselme | * Si on fait @passwd=`x_files`@ on affecte à la variable @$passwd@ le contenu de @$top_secret@ |
253 | 9 | Julien Enselme | |
254 | 9 | Julien Enselme | h1. Les redirections de flux |
255 | 1 | Julien Enselme | |
256 | 26 | Julien Enselme | h2. Les flux sortant |
257 | 26 | Julien Enselme | |
258 | 19 | Julien Enselme | Les flux représentent les sorties générées par les commandes. Par défaut, il existe deux flux : |
259 | 19 | Julien Enselme | |
260 | 19 | Julien Enselme | * Le flux standard |
261 | 19 | Julien Enselme | * Le flux d'erreur |
262 | 19 | Julien Enselme | |
263 | 19 | Julien Enselme | Par défaut, il s'affiche sur la sortie standard (votre écran pour être bref). Il peut s'avérer intéressant d'envoyer ces flux ailleurs (logs, le néant, etc.). Pour cela, on va les rediriger. Par exemple pour rediriger la sortie de @ls@ dans un fichier nommé toto, on fait : |
264 | 19 | Julien Enselme | |
265 | 19 | Julien Enselme | * @ls > toto@ |
266 | 19 | Julien Enselme | * *ou* |
267 | 19 | Julien Enselme | * @ls >> toto@ |
268 | 19 | Julien Enselme | |
269 | 19 | Julien Enselme | La première solution efface le contenu du fichier puis écrit dedans. La seconde ajoute la sortie à la fin du fichier. On a ici redirigé le flux standard. Pour rediriger les flux d'erreurs, on utilise les symboles @2>@ ou @2>>@. On peut évidemment combiner les deux : @ls -R / > mes_fichiers.txt 2> errors.log@ avec toutes les variantes possibles. |
270 | 19 | Julien Enselme | |
271 | 19 | Julien Enselme | Pour rediriger l'erreur au même endroit que l'entrée, on peut faire @ls > toto 2> toto@ ou plus simplement @ls > toto 2>&1@. |
272 | 19 | Julien Enselme | |
273 | 19 | Julien Enselme | Pour rediriger une sortie vers le néant, on l'envoie dans /dev/null. |
274 | 26 | Julien Enselme | |
275 | 26 | Julien Enselme | h2. Les flux entrant |
276 | 26 | Julien Enselme | |
277 | 26 | Julien Enselme | Il est également possible de passer en paramètre le contenu d’un fichier. Pour cela, on utilise le symbole <. |
278 | 9 | Julien Enselme | |
279 | 8 | Julien Enselme | h1. Importer une configuration |
280 | 8 | Julien Enselme | |
281 | 22 | Julien Enselme | Il est tout à fait possible d'écrire un fichier de configuration contenant les variables et les fonctions indispensables à d'autres scripts et les réutliser facilement dans ceux-ci. Pour cela, respecter la syntaxe shell dans le fichier puis au début du script qui en a besoin, placer la ligne : @. config-file.sh@ pour l'importer. |
282 | 8 | Julien Enselme | |
283 | 8 | Julien Enselme | h1. Mode debug |
284 | 1 | Julien Enselme | |
285 | 1 | Julien Enselme | Lorsqu’un de vos scripts shell bug il peut être difficile de savoir d’où vient le problème. Heureusement, le shell propose un mode débug qui vous dit pour chaque ligne comment elle est exécuté, avec quels paramètres (les variables sont remplacées par leur contenu). |
286 | 1 | Julien Enselme | |
287 | 1 | Julien Enselme | Il suffit de faire : @sh -x SCRIPT@ |
288 | 1 | Julien Enselme | |
289 | 55 | Julien Enselme | h1. Parser des arguments |
290 | 55 | Julien Enselme | |
291 | 55 | Julien Enselme | Il existe deux commandes pour parser des arguments en shell : @getopts@, qui est une commande "builtin" qui ne supporte que lse options courtes et @getopt@, qui est une commande à part, pas forcément présente mais qui supporte les arguments courts et longs. Nous n'étudierons ici que getopts qui a l'avantage d'être présent partout. |
292 | 55 | Julien Enselme | |
293 | 55 | Julien Enselme | La commande s'utilise comme suit : |
294 | 55 | Julien Enselme | <pre> |
295 | 55 | Julien Enselme | <code class="php"> |
296 | 55 | Julien Enselme | while getopts "options" opt; do |
297 | 55 | Julien Enselme | case "$opt" in |
298 | 55 | Julien Enselme | option1) action;; |
299 | 55 | Julien Enselme | esac |
300 | 55 | Julien Enselme | done |
301 | 55 | Julien Enselme | </code> |
302 | 55 | Julien Enselme | </pre> |
303 | 55 | Julien Enselme | |
304 | 55 | Julien Enselme | Ainsi, pour utiliser l'option @-o@ : |
305 | 55 | Julien Enselme | <pre> |
306 | 55 | Julien Enselme | <code class="php"> |
307 | 55 | Julien Enselme | while getopts "o" opt; do |
308 | 55 | Julien Enselme | case "$opt" in |
309 | 55 | Julien Enselme | o) echo $opt;; |
310 | 55 | Julien Enselme | esac |
311 | 55 | Julien Enselme | done |
312 | 55 | Julien Enselme | </code> |
313 | 55 | Julien Enselme | </pre> |
314 | 55 | Julien Enselme | |
315 | 55 | Julien Enselme | @script -o@ affera : @o@. Si on le lance avec l'option -a, il affichera : |
316 | 55 | Julien Enselme | <pre> |
317 | 55 | Julien Enselme | illegal option -- a |
318 | 55 | Julien Enselme | </pre> |
319 | 55 | Julien Enselme | |
320 | 55 | Julien Enselme | {{tip(Il est possible d'utiliser getopts en mode erreurs silencieux en ajoutant : au début de la chaîne des options.)}} |
321 | 55 | Julien Enselme | |
322 | 55 | Julien Enselme | Si votre option a besoin d'un argument, il suffit de placer : après son nom : |
323 | 55 | Julien Enselme | |
324 | 55 | Julien Enselme | <pre> |
325 | 55 | Julien Enselme | <code class="php"> |
326 | 55 | Julien Enselme | while getopts "ob:" opt; do |
327 | 55 | Julien Enselme | case "$opt" in |
328 | 55 | Julien Enselme | o) echo $opt;; |
329 | 55 | Julien Enselme | b) echo "$opt used with option $OPTARG";; |
330 | 55 | Julien Enselme | esac |
331 | 55 | Julien Enselme | done |
332 | 55 | Julien Enselme | </code> |
333 | 55 | Julien Enselme | </pre> |
334 | 55 | Julien Enselme | |
335 | 55 | Julien Enselme | Une fois vos arguments parser, vous pouvez mettre le premier agument positionel de votre script dans $1 avec : |
336 | 55 | Julien Enselme | |
337 | 55 | Julien Enselme | <pre> |
338 | 55 | Julien Enselme | shift $( (OPTIND-1) ) |
339 | 55 | Julien Enselme | </pre> |
340 | 55 | Julien Enselme | |
341 | 55 | Julien Enselme | Vous pouvez aussi utiliser dans le case _?_ pour afficher un message si l'utilisateur passe une option inconnue et _:_ pour afficher un message si une option qui requiert un argument ne l'a pas eu. |
342 | 55 | Julien Enselme | |
343 | 55 | Julien Enselme | |
344 | 55 | Julien Enselme | h2. Exemple |
345 | 55 | Julien Enselme | |
346 | 55 | Julien Enselme | <pre> |
347 | 55 | Julien Enselme | <code class="php"> |
348 | 55 | Julien Enselme | while getopts ":h:u:p:P" opt |
349 | 55 | Julien Enselme | do |
350 | 55 | Julien Enselme | case "$opt" in |
351 | 55 | Julien Enselme | h) |
352 | 55 | Julien Enselme | host=$OPTARG; hflag=true;; |
353 | 55 | Julien Enselme | u) |
354 | 55 | Julien Enselme | user=$OPTARG; uflag=true;; |
355 | 55 | Julien Enselme | p) |
356 | 55 | Julien Enselme | passwd=$OPTARG; pflag=true;; |
357 | 55 | Julien Enselme | P) |
358 | 55 | Julien Enselme | Pflag=true;; |
359 | 55 | Julien Enselme | :) |
360 | 55 | Julien Enselme | echo "Option -$OPTARG requires an argument." >&2 |
361 | 55 | Julien Enselme | usage; exit 1;; |
362 | 55 | Julien Enselme | \?) |
363 | 55 | Julien Enselme | usage; exit 0;; |
364 | 55 | Julien Enselme | esac |
365 | 55 | Julien Enselme | done |
366 | 55 | Julien Enselme | shift $( (OPTIND-1) ) # To get the 1st positional argument with $1 |
367 | 55 | Julien Enselme | </code> |
368 | 55 | Julien Enselme | </pre> |
369 | 55 | Julien Enselme | |
370 | 8 | Julien Enselme | h1. Différences notables avec bash |
371 | 15 | Julien Enselme | |
372 | 29 | Julien Enselme | h2. Variables disponibles uniquement en Bash |
373 | 29 | Julien Enselme | |
374 | 48 | Julien Enselme | * RANDOM (pour la génération de nombre aléatoire). Voir [[Shell_secours#Générer-des-nombres-aléatoires|ici]] pour plus de détails. |
375 | 29 | Julien Enselme | |
376 | 29 | Julien Enselme | h2. Syntaxe |
377 | 29 | Julien Enselme | |
378 | 29 | Julien Enselme | * &> et |&. Permettent de rediriger tous les flux vers un fichier ou de passer tous les flux à une commande (pipe généralisé) |
379 | 29 | Julien Enselme | * {2..10} pour générer des séquences de nombres |
380 | 45 | Julien Enselme | * @[[ ARGS ]]@ : permet de faire des tests de façon plus facile ou agréable. Exemple : @[[ chaine == chaine2 ]]@ |
381 | 45 | Julien Enselme | * =~ : s'utilse conjointement avec @[[ ]]@ pour tester si la chaîne de gauche est contenu dans celle de droite |
382 | 38 | Julien Enselme | * $((ARGS)) est un raccourcis pour la fonction let |
383 | 29 | Julien Enselme | |
384 | 29 | Julien Enselme | h2. Autres |
385 | 29 | Julien Enselme | |
386 | 29 | Julien Enselme | * Le nombre de paramètres en bash n'est pas limité à 9. Les paramètres positionnels de numéros supérieurs à 10 s'appellent comme suit : ${num} |
387 | 18 | Julien Enselme | |
388 | 1 | Julien Enselme | h1. Divers |
389 | 1 | Julien Enselme | |
390 | 7 | Julien Enselme | h2. Différences entre la sortie de ls et de find |
391 | 9 | Julien Enselme | |
392 | 28 | Julien Enselme | * @ls@ renvoie simplement la liste des fichiers. |
393 | 28 | Julien Enselme | * @find@ renvoie un chemin absolu si l’argument donnée est un chemin absolu et relatif (de la forme ./fichier) si l’argument est . |
394 | 18 | Julien Enselme | |
395 | 40 | Julien Enselme | h2. ET et OU dans le langage |
396 | 40 | Julien Enselme | |
397 | 40 | Julien Enselme | L’opérateur && permet de réaliser un ET paresseux entre deux commandes. Ainsi, par exemple : @cmd1 && cmd2@. @cmd2@ ne sera exécuté que si @cmd1@ a pu s’exécuter correctement. En outre le code de retour de l’ensemble ne sera 0 que si les deux commandes ont pu s’exécuter correctement. |
398 | 40 | Julien Enselme | |
399 | 40 | Julien Enselme | L’opérateur || permet de réaliser un OU paresseux entre deux commandes. Ainsi, par exemple : @cmd1 || cmd2@. Si @cmd1@ s’exécute correctement @cmd2@ ne sera pas exécutée. Si @cmd1@ retourne une erreur, @cmd2@ sera exécutée. Le code de retour de l’ensemble correspond à un OU entre les deux codes de retour. |
400 | 40 | Julien Enselme | |
401 | 40 | Julien Enselme | Ceci peut s’utiliser [[Petit_precis_de_shell#La-fonction-test|avec la fonction test]]. |
402 | 40 | Julien Enselme | |
403 | 40 | Julien Enselme | Des fonctionnalités analogues existes dans d’autres langages inspirés du shell comme Perl ou PHP. |
404 | 40 | Julien Enselme | |
405 | 40 | Julien Enselme | Pour exécuter simplement deux commandes à la suite des autres sur une seule ligne, il suffit de séparer les commandes par un point virgule. |
406 | 40 | Julien Enselme | |
407 | 42 | Julien Enselme | h2. Différences entre les implémentations de certaines commandes entre GNU et BSD |
408 | 42 | Julien Enselme | |
409 | 42 | Julien Enselme | h3. sed |
410 | 42 | Julien Enselme | |
411 | 53 | Julien Enselme | La commande @sed@ de BSD ne connaît pas certains métacaractères tels que \s. |
412 | 53 | Julien Enselme | |
413 | 53 | Julien Enselme | Les opérations dans un fichier se font : @sed -i'' 's/toto/tata/g' fichier@ sous GNU mais @sed -i '' 's/toto/tata/g' fichier@ sous BSD. La commande @sed -i -e s/toto/tata/g' fichier@ est compatible avec les deux versions. |
414 | 42 | Julien Enselme | |
415 | 50 | Julien Enselme | h1. Opérations avancées sur les variables |
416 | 50 | Julien Enselme | |
417 | 50 | Julien Enselme | h2. Valeurs par défaut |
418 | 50 | Julien Enselme | |
419 | 50 | Julien Enselme | Il est tout à fait possible de donner une valeur par défaut à une variable en bash. Ainsi, le code suivant : @FOO=${FOO:-coucou}@ signifie que : |
420 | 50 | Julien Enselme | * Si la variable FOO est définie, alors ne rien faire |
421 | 50 | Julien Enselme | * Si FOO n'est pas définie, alors FOO vaut 'coucou' |
422 | 50 | Julien Enselme | |
423 | 50 | Julien Enselme | Cela fonctionne aussi avec une autre variable : @FOO=${toto:-coucou}@. Cette fois, FOO prendra la valeur 'coucou' si toto n'est pas définie. Cette forme laisse toto inchangée. Pour affecter 'coucou' a foo et toto : @FOO=${toto:=coucou}@. |
424 | 50 | Julien Enselme | |
425 | 51 | Julien Enselme | h2. Travailler avec les chemins |
426 | 51 | Julien Enselme | |
427 | 51 | Julien Enselme | Le shell dispose de moyen de travailler avec les chemins de façon facile et agréable : |
428 | 51 | Julien Enselme | * Supprimer le dernier / : @${a%/}@ |
429 | 51 | Julien Enselme | * Supprimer le premier / : @${#*/}@ |
430 | 51 | Julien Enselme | * Récupérer le dossier courant : @${a##*/}@ (si a ne se termine pas par /) |
431 | 51 | Julien Enselme | * Récupérer le dossier parent : @${a%/*}@ |
432 | 51 | Julien Enselme | |
433 | 18 | Julien Enselme | h1. Sources et liens externes |
434 | 1 | Julien Enselme | |
435 | 30 | Julien Enselme | * http://www.siteduzero.com/informatique/tutoriels/reprenez-le-controle-a-l-aide-de-linux |
436 | 18 | Julien Enselme | * http://www.commentcamarche.net/faq/5444-bash-les-parametres |