Projet

Général

Profil

Petit precis de shell » Historique » Version 61

Julien Enselme, 28/03/2015 12:03

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 61 Julien Enselme
Jenselme en propose "une version plus complète sur son site":http://www.jujens.eu/posts/2014/Sep/07/petit-precis-shell/.
4 61 Julien Enselme
5 49 Julien Enselme
{{>toc}}
6 1 Julien Enselme
7 3 Julien Enselme
h1. Quelques rappels d'Unix
8 3 Julien Enselme
9 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.
10 3 Julien Enselme
11 3 Julien Enselme
Comme pour la plupart des langages de script, il existe deux façons d'exécuter des instructions shell :
12 3 Julien Enselme
13 3 Julien Enselme
* directement dans l'interpréteur
14 3 Julien Enselme
* dans un script shell
15 3 Julien Enselme
16 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.
17 3 Julien Enselme
18 1 Julien Enselme
h1. Les bases du shell
19 3 Julien Enselme
20 4 Julien Enselme
Il est très important de comprendre et de garder à l'esprit qu'en shell tout est :
21 4 Julien Enselme
22 4 Julien Enselme
* chaîne de caractères (y compris les nombres) ! Entrez @echo 1 + 1@ dans le terminal pour vous en convaincre.
23 4 Julien Enselme
* commande et que donc elles peuvent prendre des arguments (cela s'éclaircira plus tard)
24 4 Julien Enselme
25 4 Julien Enselme
h2. Syntaxe de base
26 4 Julien Enselme
27 4 Julien Enselme
Les commandes s'écrivent soit :
28 4 Julien Enselme
29 6 Florent Torregrosa
* les unes à la suite des autres séparées par ; (peu recommandé)
30 4 Julien Enselme
* séparées les unes des autres par un saut de ligne
31 4 Julien Enselme
32 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 :
33 4 Julien Enselme
34 32 Julien Enselme
* les options courtes (l, r, h pour @ls@ par exemple) qui sont passés comme suit : @CMD -ARG@
35 32 Julien Enselme
* les options longues (recursive pour @rsync@ par exemple) qui se passent comme ceci : @CMD --ARGUMENT@
36 4 Julien Enselme
37 32 Julien Enselme
Il est évidement possible de passer plusieurs options à une même commande.
38 1 Julien Enselme
39 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.)}}
40 1 Julien Enselme
41 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))}}
42 32 Julien Enselme
43 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.
44 32 Julien Enselme
45 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.
46 32 Julien Enselme
47 32 Julien Enselme
{{tip(Pensez à la commande man qui prend comme argument une autre commande et affiche son manuel)}}
48 4 Julien Enselme
49 33 Julien Enselme
h2. Valeurs de retour des commandes et exceptions
50 5 Julien Enselme
51 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 :
52 5 Julien Enselme
53 5 Julien Enselme
* 0 : tout va bien
54 5 Julien Enselme
* 1 : erreur
55 5 Julien Enselme
* 2 : erreur grave
56 5 Julien Enselme
57 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é.
58 5 Julien Enselme
59 46 Julien Enselme
Vous pouvez connaître la valeur de retour de la dernière commande exécutée avec la variable @$?@.
60 46 Julien Enselme
61 13 Julien Enselme
h2. Exécuter une commande
62 13 Julien Enselme
63 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.
64 13 Julien Enselme
65 13 Julien Enselme
Pour obtenir le résultat souhaité vous devez placer CMS entre backquote `` ou entre $(…). Par exemple : @var=`ls`@ ou @var=$(ls)@.
66 13 Julien Enselme
67 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é.
68 13 Julien Enselme
69 4 Julien Enselme
h2. Conditions et itérations
70 7 Julien Enselme
71 11 Julien Enselme
h3. Conditions if … else …
72 7 Julien Enselme
73 7 Julien Enselme
La structure générale d'une condition est la suivante :
74 7 Julien Enselme
75 7 Julien Enselme
<pre>
76 7 Julien Enselme
<code>
77 7 Julien Enselme
if QQC
78 7 Julien Enselme
then
79 7 Julien Enselme
    CMDS
80 7 Julien Enselme
else
81 7 Julien Enselme
    CMDS
82 7 Julien Enselme
fi
83 7 Julien Enselme
</code>
84 7 Julien Enselme
</pre>
85 7 Julien Enselme
86 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@.
87 7 Julien Enselme
88 7 Julien Enselme
La question que vous devriez avoir est que mettre à la place de @QQC@. Il y a deux possibilités :
89 7 Julien Enselme
90 7 Julien Enselme
* la fonction @test@
91 7 Julien Enselme
* une commande
92 7 Julien Enselme
93 11 Julien Enselme
h4. La fonction test
94 7 Julien Enselme
95 7 Julien Enselme
{{important(Dans toute la suite, il faudra faire très *attention aux espaces*)}}
96 7 Julien Enselme
97 34 Julien Enselme
La fonction @test@ s'utilise en général comme suit : @if [ ARGS ]@ *Notez les espaces !*
98 7 Julien Enselme
99 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]]
100 7 Julien Enselme
101 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@.
102 10 Julien Enselme
103 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.
104 10 Julien Enselme
105 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]].)}}
106 41 Julien Enselme
107 10 Julien Enselme
Voir ci-dessous pour la liste complète.
108 10 Julien Enselme
109 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))}}
110 10 Julien Enselme
111 21 Julien Enselme
*Tests sur les chaînes de caractères*
112 21 Julien Enselme
113 10 Julien Enselme
|_. Argument |_. Signification |
114 10 Julien Enselme
| = | égalité |
115 1 Julien Enselme
| -z | chaîne vide |
116 1 Julien Enselme
| -n | chaîne non vide |
117 21 Julien Enselme
118 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é)}}
119 47 Julien Enselme
120 21 Julien Enselme
*Tests sur les nombres*
121 21 Julien Enselme
122 10 Julien Enselme
|_. Argument |_. Signification |
123 10 Julien Enselme
| -eq | égalité |
124 34 Julien Enselme
| -ne | différent |
125 10 Julien Enselme
| -lt | strictement plus petit |
126 10 Julien Enselme
| -gt | strictement plus grand |
127 10 Julien Enselme
| -ge | plus grand ou égal |
128 10 Julien Enselme
| -le | plus petit ou égal |
129 10 Julien Enselme
130 7 Julien Enselme
h4. Test avec une commande
131 1 Julien Enselme
132 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@.
133 10 Julien Enselme
134 10 Julien Enselme
{{tip(Parfois vous pourrez rencontrer des problèmes. Pensez alors à donner cette commande en argument à la fonction test)}}
135 7 Julien Enselme
136 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.)}}
137 54 Julien Enselme
138 12 Julien Enselme
h3. Boucles while/until
139 12 Julien Enselme
140 12 Julien Enselme
La structure générale est la suivante :
141 12 Julien Enselme
<pre>
142 12 Julien Enselme
while QQC
143 12 Julien Enselme
do
144 12 Julien Enselme
    CMD
145 12 Julien Enselme
done
146 12 Julien Enselme
</pre>
147 12 Julien Enselme
148 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.
149 12 Julien Enselme
150 12 Julien Enselme
Le shell propose également le mot clé @until QQC@ qui fait une action jusqu’à ce que QQC soit réalisé.
151 12 Julien Enselme
152 12 Julien Enselme
h3. Boucle for
153 12 Julien Enselme
154 12 Julien Enselme
L’utilisation de la boucle for en shell ressemble à celle de python. La structure générale est la suivante :
155 12 Julien Enselme
<pre>
156 12 Julien Enselme
for var in `CMD`
157 12 Julien Enselme
do
158 12 Julien Enselme
   CMD
159 12 Julien Enselme
done
160 12 Julien Enselme
</pre>
161 12 Julien Enselme
162 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@.
163 12 Julien Enselme
164 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`@
165 16 Julien Enselme
166 18 Julien Enselme
h1. Paramètres de scripts
167 18 Julien Enselme
168 18 Julien Enselme
h2. Généralités
169 18 Julien Enselme
170 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 :
171 18 Julien Enselme
172 18 Julien Enselme
* une variable
173 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 ".
174 18 Julien Enselme
175 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_)}}
176 18 Julien Enselme
177 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 :
178 18 Julien Enselme
179 18 Julien Enselme
* le premier : $1
180 18 Julien Enselme
* le deuxième : $2
181 18 Julien Enselme
* et ainsi de suite
182 18 Julien Enselme
183 18 Julien Enselme
{{important(Le shell ne supporte *que* 9 paramètres)}}
184 18 Julien Enselme
185 18 Julien Enselme
h2. Les paramètres spéciaux
186 18 Julien Enselme
187 18 Julien Enselme
* $0 : contient le nom du script
188 18 Julien Enselme
* $# : contient le nombre d'arguments passés au script
189 36 Julien Enselme
{{important(Le paramète $0 est toujours passé au script. $# est donc toujours supérieur ou égal à 1)}}
190 18 Julien Enselme
* $? : le code de retour de la dernière commande invoquée
191 18 Julien Enselme
* $$ : le PID du shell qui exécute le script
192 1 Julien Enselme
* $! : le PID du dernier processus lancé en arrière plan
193 25 Julien Enselme
* $* : l'ensemble des paramètres en un seul argument
194 25 Julien Enselme
* $@ : L'ensemble des arguments, un argument par paramètre
195 25 Julien Enselme
196 36 Julien Enselme
Pour bien voir la différence entre $* et $@, il suffit de regarder la sortie du script suivant : 
197 25 Julien Enselme
<pre>
198 25 Julien Enselme
<code class="bash">
199 25 Julien Enselme
echo 'Avec $*'
200 25 Julien Enselme
for param in "$*" ; do
201 25 Julien Enselme
  echo $param
202 25 Julien Enselme
done
203 25 Julien Enselme
204 25 Julien Enselme
echo 'Avec $@'
205 25 Julien Enselme
for param in "$@" ; do
206 25 Julien Enselme
  echo $param
207 25 Julien Enselme
done
208 25 Julien Enselme
</code>
209 25 Julien Enselme
</pre>
210 18 Julien Enselme
211 18 Julien Enselme
h2. Les commandes shift et set
212 18 Julien Enselme
213 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.
214 18 Julien Enselme
215 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.
216 18 Julien Enselme
217 17 Julien Enselme
h1. Les fonctions
218 17 Julien Enselme
219 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.
220 17 Julien Enselme
221 17 Julien Enselme
<pre>
222 39 Julien Enselme
nom_de_la-fonction () {
223 17 Julien Enselme
  CMDS
224 17 Julien Enselme
}
225 17 Julien Enselme
</pre>
226 1 Julien Enselme
227 39 Julien Enselme
ou encore
228 39 Julien Enselme
229 39 Julien Enselme
<pre>
230 39 Julien Enselme
function nom_de_la-fonction {
231 39 Julien Enselme
  CMDS
232 39 Julien Enselme
}
233 39 Julien Enselme
</pre>
234 39 Julien Enselme
235 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 :
236 17 Julien Enselme
237 39 Julien Enselme
* la portée des variables
238 17 Julien Enselme
* la valeur de retour
239 17 Julien Enselme
240 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).
241 17 Julien Enselme
242 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 :
243 17 Julien Enselme
244 17 Julien Enselme
<pre>
245 17 Julien Enselme
<code class="bash">
246 17 Julien Enselme
x_files () {
247 17 Julien Enselme
  top_secret=`dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -f1 -d" "`
248 17 Julien Enselme
  echo $top_secret
249 8 Julien Enselme
}
250 8 Julien Enselme
</code>
251 8 Julien Enselme
</pre>
252 9 Julien Enselme
253 9 Julien Enselme
* Si on fait @x_files@ on affiche à l'écran le contenu de @$top_secret@
254 9 Julien Enselme
* Si on fait @passwd=`x_files`@ on affecte à la variable @$passwd@ le contenu de @$top_secret@
255 9 Julien Enselme
256 9 Julien Enselme
h1. Les redirections de flux
257 1 Julien Enselme
258 26 Julien Enselme
h2. Les flux sortant
259 26 Julien Enselme
260 19 Julien Enselme
Les flux représentent les sorties générées par les commandes. Par défaut, il existe deux flux :
261 19 Julien Enselme
262 19 Julien Enselme
* Le flux standard
263 19 Julien Enselme
* Le flux d'erreur
264 19 Julien Enselme
265 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 :
266 19 Julien Enselme
267 19 Julien Enselme
* @ls > toto@
268 19 Julien Enselme
* *ou*
269 19 Julien Enselme
* @ls >> toto@
270 19 Julien Enselme
271 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.
272 19 Julien Enselme
273 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@.
274 19 Julien Enselme
275 19 Julien Enselme
Pour rediriger une sortie vers le néant, on l'envoie dans /dev/null.
276 26 Julien Enselme
277 26 Julien Enselme
h2. Les flux entrant
278 26 Julien Enselme
279 26 Julien Enselme
Il est également possible de passer en paramètre le contenu d’un fichier. Pour cela, on utilise le symbole <.
280 9 Julien Enselme
281 8 Julien Enselme
h1. Importer une configuration
282 8 Julien Enselme
283 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.
284 8 Julien Enselme
285 8 Julien Enselme
h1. Mode debug
286 1 Julien Enselme
287 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).
288 1 Julien Enselme
289 1 Julien Enselme
Il suffit de faire : @sh -x SCRIPT@
290 1 Julien Enselme
291 55 Julien Enselme
h1. Parser des arguments
292 55 Julien Enselme
293 59 Florent Torregrosa
Il existe deux commandes pour parser des arguments en shell : @getopts@, qui est une commande "builtin" qui ne supporte que les 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.
294 55 Julien Enselme
295 55 Julien Enselme
La commande s'utilise comme suit :
296 55 Julien Enselme
<pre>
297 55 Julien Enselme
<code class="php">
298 55 Julien Enselme
while getopts "options" opt; do
299 55 Julien Enselme
  case "$opt" in
300 55 Julien Enselme
    option1) action;;
301 55 Julien Enselme
  esac
302 55 Julien Enselme
done
303 55 Julien Enselme
</code>
304 55 Julien Enselme
</pre>
305 55 Julien Enselme
306 55 Julien Enselme
Ainsi, pour utiliser l'option @-o@ :
307 55 Julien Enselme
<pre>
308 55 Julien Enselme
<code class="php">
309 55 Julien Enselme
while getopts "o" opt; do
310 55 Julien Enselme
  case "$opt" in
311 55 Julien Enselme
    o) echo $opt;;
312 55 Julien Enselme
  esac
313 55 Julien Enselme
done
314 55 Julien Enselme
</code>
315 55 Julien Enselme
</pre>
316 55 Julien Enselme
317 55 Julien Enselme
@script -o@ affera : @o@. Si on le lance avec l'option -a, il affichera :
318 55 Julien Enselme
<pre>
319 55 Julien Enselme
illegal option -- a
320 55 Julien Enselme
</pre>
321 55 Julien Enselme
322 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.)}}
323 55 Julien Enselme
324 55 Julien Enselme
Si votre option a besoin d'un argument, il suffit de placer : après son nom :
325 55 Julien Enselme
326 55 Julien Enselme
<pre>
327 55 Julien Enselme
<code class="php">
328 55 Julien Enselme
while getopts "ob:" opt; do
329 55 Julien Enselme
  case "$opt" in
330 55 Julien Enselme
    o) echo $opt;;
331 55 Julien Enselme
    b) echo "$opt used with option $OPTARG";;
332 55 Julien Enselme
  esac
333 55 Julien Enselme
done
334 55 Julien Enselme
</code>
335 55 Julien Enselme
</pre>
336 55 Julien Enselme
337 55 Julien Enselme
Une fois vos arguments parser, vous pouvez mettre le premier agument positionel de votre script dans $1 avec :
338 55 Julien Enselme
339 57 Julien Enselme
@shift $(@(OPTIND-1)@)@
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
h2. Exemple
344 55 Julien Enselme
345 55 Julien Enselme
<pre>
346 55 Julien Enselme
<code class="php">
347 55 Julien Enselme
while getopts ":h:u:p:P" opt
348 55 Julien Enselme
do
349 55 Julien Enselme
    case "$opt" in
350 55 Julien Enselme
        h)
351 55 Julien Enselme
            host=$OPTARG; hflag=true;;
352 55 Julien Enselme
        u)
353 55 Julien Enselme
            user=$OPTARG; uflag=true;;
354 55 Julien Enselme
        p)
355 55 Julien Enselme
            passwd=$OPTARG; pflag=true;;
356 55 Julien Enselme
        P)
357 55 Julien Enselme
            Pflag=true;;
358 55 Julien Enselme
        :)
359 55 Julien Enselme
            echo "Option -$OPTARG requires an argument." >&2
360 55 Julien Enselme
            usage; exit 1;;
361 55 Julien Enselme
        \?)
362 55 Julien Enselme
            usage; exit 0;;
363 55 Julien Enselme
    esac
364 55 Julien Enselme
done
365 55 Julien Enselme
</code>
366 58 Julien Enselme
shift $(@(OPTIND-1)@) # To get the 1st positional argument with $1
367 55 Julien Enselme
</pre>
368 55 Julien Enselme
369 8 Julien Enselme
h1. Différences notables avec bash
370 15 Julien Enselme
371 29 Julien Enselme
h2. Variables disponibles uniquement en Bash
372 29 Julien Enselme
373 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.
374 29 Julien Enselme
375 29 Julien Enselme
h2. Syntaxe
376 29 Julien Enselme
377 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é)
378 29 Julien Enselme
* {2..10} pour générer des séquences de nombres
379 45 Julien Enselme
* @[[ ARGS ]]@ : permet de faire des tests de façon plus facile ou agréable. Exemple : @[[ chaine == chaine2 ]]@
380 45 Julien Enselme
* =~ : s'utilse conjointement avec @[[ ]]@ pour tester si la chaîne de gauche est contenu dans celle de droite
381 56 Julien Enselme
* $(@(ARGS)@) est un raccourcis pour la fonction let
382 29 Julien Enselme
383 29 Julien Enselme
h2. Autres
384 29 Julien Enselme
385 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}
386 18 Julien Enselme
387 1 Julien Enselme
h1. Divers
388 1 Julien Enselme
389 7 Julien Enselme
h2. Différences entre la sortie de ls et de find
390 9 Julien Enselme
391 28 Julien Enselme
* @ls@ renvoie simplement la liste des fichiers.
392 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 .
393 18 Julien Enselme
394 40 Julien Enselme
h2. ET et OU dans le langage
395 40 Julien Enselme
396 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.
397 40 Julien Enselme
398 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.
399 40 Julien Enselme
400 40 Julien Enselme
Ceci peut s’utiliser [[Petit_precis_de_shell#La-fonction-test|avec la fonction test]].
401 40 Julien Enselme
402 40 Julien Enselme
Des fonctionnalités analogues existes dans d’autres langages inspirés du shell comme Perl ou PHP.
403 40 Julien Enselme
404 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.
405 40 Julien Enselme
406 42 Julien Enselme
h2. Différences entre les implémentations de certaines commandes entre GNU et BSD
407 42 Julien Enselme
408 42 Julien Enselme
h3. sed
409 42 Julien Enselme
410 53 Julien Enselme
La commande @sed@ de BSD ne connaît pas certains métacaractères tels que \s.
411 53 Julien Enselme
412 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.
413 42 Julien Enselme
414 50 Julien Enselme
h1. Opérations avancées sur les variables
415 50 Julien Enselme
416 50 Julien Enselme
h2. Valeurs par défaut
417 50 Julien Enselme
418 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 :
419 50 Julien Enselme
* Si la variable FOO est définie, alors ne rien faire
420 50 Julien Enselme
* Si FOO n'est pas définie, alors FOO vaut 'coucou'
421 50 Julien Enselme
422 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}@.
423 50 Julien Enselme
424 51 Julien Enselme
h2. Travailler avec les chemins
425 51 Julien Enselme
426 51 Julien Enselme
Le shell dispose de moyen de travailler avec les chemins de façon facile et agréable :
427 51 Julien Enselme
* Supprimer le dernier / : @${a%/}@
428 51 Julien Enselme
* Supprimer le premier / : @${#*/}@
429 51 Julien Enselme
* Récupérer le dossier courant : @${a##*/}@ (si a ne se termine pas par /)
430 51 Julien Enselme
* Récupérer le dossier parent : @${a%/*}@
431 51 Julien Enselme
432 18 Julien Enselme
h1. Sources et liens externes
433 1 Julien Enselme
434 60 Julien Enselme
* Quelques règles de style. *Certains points ne s'appliquent qu'à bash* : http://google-styleguide.googlecode.com/svn/trunk/shell.xml
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