Vous êtes sur la page 1sur 30

Filière Dev C-C++, Linux embarqué

Scripts shell
le 22 et les 25-26 février 2019

© Copyright 2019 AJC formation - Sébastien Huss


Table des matières 2/30

3. Introduction
3. Mon 1er script shell
4. Variables positionnelles
5. Tableau
6. Les codes de retour
7. Evaluations
7. Booléens et opérations
8. test
9. Tests améliorés
10. Tests arithmétiques améliorés
11. Compter
11. expr
12. Arithmétique des shells modernes
13. bc
14. Structures
14. if
15. case
16. while

17. until
18. for
19. select
20. Groupes
21. Debug
22. sed avancé
23. Exercices
23. Menu
24. Solution
25. Table de multiplication
26. Solution
27. Information sur un utilisateur
28. Solution
29. index.html
30. Solution

© Copyright 2019 AJC formation - Sébastien Huss


Introduction 3/30
Mon 1er script shell
#!/bin/bash

# Ceci n'est pas un "hello world"

echo "mon premier script shell"

Permissions et lancement :
$ chmod 755 script.sh
$ ./script.sh
mon premier script shell

© Copyright 2019 AJC formation - Sébastien Huss


Introduction 4/30
Variables positionnelles

$# : Nombre d'argument
$1 : 1er argument
$2 : 2eme argument
...
$* et $@
set -- a b c
shift

© Copyright 2019 AJC formation - Sébastien Huss


Introduction 5/30
Tableau
$ TAB=(A B C D E)
$ typeset -p TAB
declare -a TAB=([0]="A" [1]="B" [2]="C" [3]="D" [4]="E")
$ echo ${TAB[0]}
A
$ echo "${TAB[@]}"
A B C D E
$ echo "${#TAB[@]}"
5
$ TAB[5]="F"
$ TAB+=(G)
$ TAB=("#" "${TAB[@]}")
$ typeset -p TAB
declare -a TAB=([0]="#" [1]="A" [2]="B" [3]="C" [4]="D" [5]="E" [6]="F" [7]="G")
$ echo "${TAB[@]:1:6}"
A B C D E F
$ TAB=("${TAB[@]:1}")

© Copyright 2019 AJC formation - Sébastien Huss


Introduction 6/30
Les codes de retour

$?
de 0 a 255
0 signi e succès, OK
Positionner le code retour avec :
return
exit

$ true; echo $?
0
$ false;echo $?
1

© Copyright 2019 AJC formation - Sébastien Huss


Evaluations 7/30
Booléens et opérations

en shell 0 est "vrai"


tout autre code retour est "faux"
$ true && echo vrai
vrai
$ false || echo faux
faux

© Copyright 2019 AJC formation - Sébastien Huss


Evaluations 8/30
test

Les évaluations sont normalement réalisées avec test.


On utilise majoritairement la notation [ ... ]
Fichiers Chaînes
[ -e file ] # existance de fichier/répertoire [ -z "" ] # la chaîne est vide
! [ -e file ] # n'existe pas [ -n "x" ] # La chaîne est non vide
[ -d dir ] # est un répertoire [ "a" = "a" ] # Les chaînes sont identiques
[ -f file ] # est un fichier [ "a" != "b" ] # Les chaînes sont différentes
[ -r file ] # est lisible
[ -w file ] # l'utilisateur courant a le droi
[ -x file ] # l'utilisateur courant a le droi
[
[
-O file ] # l'utilisateur courant est le pr
f1 -nt f2 ] # f1 est plus récent que f2 (newe
Entiers
[ f1 -ot f2 ] # f1 est plus vieux que f2 (older
[ 0 -eq 0 ] # Les entiers sont égaux
[ 1 -ne 0 ] # les entiers sont differents
[ 0 -le 1 ] # 0 est inférieur ou égal à 1
[ 0 -lt 1 ] # 0 est inférieur à 1
[ 1 -ge 0 ] # 1 est supérieur ou égal à 0
[ 1 -gt 0 ] # 1 est supérieur à 0

© Copyright 2019 AJC formation - Sébastien Huss


Evaluations 9/30
Tests améliorés

bash et ksh disposent de [[ ... Amélioration


]]
[ 0 -eq 0 ] && [ 1 -ne 0 ]
Amélioration de [ ... ] [[ 0 -eq 0 && 1 -ne 0 ]]

! [ -e file ]
[[ ! -e file ]]

[ -z "$VAL" ]
[[ -z $VAL ]]

Correspondance de chaînes
[[ $VAL = y* ]] # VAL commence par "y"
[[ $VAL =~ ^y ]] # VAL commence par "y"

© Copyright 2019 AJC formation - Sébastien Huss


Evaluations 10/30
Tests arithmétiques améliorés

bash et ksh seulement


(( 0 = 0 )) # Les entiers sont égaux
(( 1 != 0 )) # les entiers sont différents
(( 0 < 1 )) # 0 est inférieur ou égal à 1
(( 0 <= 1 )) # 0 est inférieur à 1
(( 1 > 0 )) # 1 est supérieur ou égal à 0
(( 1 >= 0 )) # 1 est supérieur à 0

© Copyright 2019 AJC formation - Sébastien Huss


Compter 11/30
expr
$ expr 2 + 1
3
$ expr 2 '*' 10
20
$ expr 1+2
1+2
$ expr 20 / 3
6
$ RES=$(expr 20 / 5 )

© Copyright 2019 AJC formation - Sébastien Huss


Compter 12/30
Arithmétique des shells modernes
$ echo $((2+1))
3
$ echo $((2*10))
20
$ RES=$((20/5))
$ ((RES=20/5))
$ echo $RES
4
$ ((RES++));echo $RES
5

© Copyright 2019 AJC formation - Sébastien Huss


Compter 13/30
bc

La seule solution pour travailler avec des nombres à virgule


$ echo 30 / 11 |bc
2
$ echo 30 / 11 |bc -l
2.72727272727272727272
$ bc -l <<< "30/11"
2.72727272727272727272
$ RES=$(bc -l <<< "30/11")
$ alias math="bc -l <<<"
$ math "30/11"
2.72727272727272727272

© Copyright 2019 AJC formation - Sébastien Huss


Structures 14/30
if
if false;then
echo Impossible
elif ((2>4));then
echo Impossible
else
echo "Et oui"
fi

© Copyright 2019 AJC formation - Sébastien Huss


Structures 15/30
case
case "$1" in
-h|--help)
show_help
exit 0;;
-a)
echo "utilise -a";;
-*)
echo "Option '$1' inconnue" >&2
show_help
exit 1;;
*)
echo "Argument 1 est $1";;
esac

© Copyright 2019 AJC formation - Sébastien Huss


Structures 16/30
while

i=0; while read line;do


while ((i<10));do echo "$line";
echo "$i"; done</etc/group
((i++))
done
Utilisation de IFS
IFS=:
while read group x gid users;do
printf '%6d | %-20s | %s\n' "$gid" "$gr
done</etc/group
unset IFS

Utilisation de IFS et set


while read line;do
IFS=:;set -- $line;unset IFS
printf '%6d | %-20s | %s\n' "$3" "$1" "
done</etc/group

© Copyright 2019 AJC formation - Sébastien Huss


Structures 17/30
until
i=0;
until (($i>=10));do
echo "$i";
((i++))
done

© Copyright 2019 AJC formation - Sébastien Huss


Structures 18/30
for

for i in /usr/share/doc/b*;do for ((i=0;i<10;i++));do


echo "$i"; echo "$i";
done done

for i in $(seq 0 9);do


echo "$i";
done

© Copyright 2019 AJC formation - Sébastien Huss


Structures 19/30
select
select VAL in "homme" "femme";do
case "$VAL" in
homme)
echo Bonjour Monsieur;
break;;
femme)
echo Mes hommages Madame
break;;
*)
echo "entrée non valide" >&2
esac
done

© Copyright 2019 AJC formation - Sébastien Huss


Structures 20/30
Groupes

Les fonctions Groupe de commandes


fnct() { $ { grep seb /etc/passwd;grep root /etc/passwd;
local user=${1:-'root'} awk -F: '{print "le shell de "$1" est "$7}'
id $user le shell de seb est /bin/bash
return 0 le shell de root est /bin/bash
} $ { A=5; }
setRC() { $ echo $A
return ${1:-0} 5
}

Sous-shell
$ ( exit 4 ) || echo "En échec"
En échec
$ A=10
$ ( echo "A=$A"; A=20; echo "A=$A" )
A=10
A=20
$ echo "A=$A"
A=10

© Copyright 2019 AJC formation - Sébastien Huss


Debug 21/30

Option Effet
set - Arrête le script au premier code retour faux
e
set - Analyse les commandes sans les éxecuter
n
set - Af che les commandes (telles que dans le code)
v
set - Af che les commandes au fur et à mesure après évaluation
x

© Copyright 2019 AJC formation - Sébastien Huss


sed avancé 22/30

Réutiliser les "matchs" Ajouter avant, après et remplacer


une ligne
$ echo "Ceci est une phrase simple."|\
sed 's/\([a-zA-Z]*\) \([a-zA-Z]*\)/\2 \1/'
est Ceci une phrase simple. $ echo -e "xx WORD xx\n----\noo WORD ooo"|sed '
i\
Ajoute cette ligne avant
Les intervalles a\
Ajoute cette ligne après
c\
$ sed -n '/:20:/,/:30:/ s/:.*// p'</etc/group Remplace la ligne par ceci
$ sed -n '/:20:/,/:30:/ {s/:.*// p}'</etc/group }'

Plusieurs commandes Transformer (a la "tr")


$ echo "Ceci est une phrase simple."|\ $ echo "Ceci est une phrase simple."|\
sed 's/Ceci est/Voici/;s/simple/éditée/' sed 'y/aceispm/ACEISPM/'
Voici une phrase éditée. CECI ESt unE PhrASE SIMPlE.

© Copyright 2019 AJC formation - Sébastien Huss


Exercices 23/30
Menu

Réaliser un script qui demande Nom, Prénom, Sexe et age en validant


les données et af che une synthèse

© Copyright 2019 AJC formation - Sébastien Huss


Exercices 24/30
Solution

#!/bin/bash age)
question() { printf '%20s : ' "$1"; read $2; } affiche Nom "$nom"
affiche() { printf '%20s : %s\n' "$1" "$2"; } affiche Prenom "$prenom"
affiche Sexe "$sexe"
STEP=nom question Age age
until [[ $STEP == "done" ]];do if [[ $age =~ ^[0-9]+$ ]];then
clear STEP=fin;
echo else
if [[ -n $ERROR ]];then ERROR="'$age' n'st pas un age valide. Veuillez entrer
printf '\t\t\e[1;31m%s\e[0m\n' "$ERROR" fi;;
else echo; fin)
fi; affiche Nom "$nom"
echo;echo; affiche Prenom "$prenom"
ERROR="" affiche Sexe "$sexe"
case "$STEP" in affiche Age "$age"
nom) printf '\n\n\n\n'
question Nom nom; STEP=done;;
STEP=prenom;; esac
prenom) done
affiche Nom "$nom"
question Prenom prenom
STEP=sexe;;
sexe)
affiche Nom "$nom"
affiche Prenom "$prenom"
echo
affiche 1 homme
affiche 2 femme
question "Sexe" r
case "$r" in
1) sexe=homme
STEP=age;;
2) sexe=femme
STEP=age;;
*) ERROR="'$r' n'est pas une réponse valide. Répondre 1 o
esac;;

© Copyright 2019 AJC formation - Sébastien Huss


Exercices 25/30
Table de multiplication

Réaliser un script qui génère la table complète de multiplication de


tous les chiffres de 1 à 10 en utilisant une boucle until et une boucle
for. Résultat du script attendu :
* # 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
---#-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
1 # 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
---#-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
2 # | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20
---#-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
3 # | | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30
---#-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
4 # | | | 16 | 20 | 24 | 28 | 32 | 36 | 40
---#-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
5 # | | | | 25 | 30 | 35 | 40 | 45 | 50
---#-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
6 # | | | | | 36 | 42 | 48 | 54 | 60
---#-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
7 # | | | | | | 49 | 56 | 63 | 70
---#-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
8 # | | | | | | | 64 | 72 | 80
---#-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
9 # | | | | | | | | 81 | 90
---#-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
10 # | | | | | | | | | 100
© Copyright 2019 AJC formation - Sébastien Huss
Exercices 26/30
Solution
#!/bin/bash
echo ' * # 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10'
A=1;until ((A>10));do
echo '---#-----+-----+-----+-----+-----+-----+-----+-----+-----+-----'
printf '%2d #' $A
for ((B=1;B<10;B+=1));do
if ((B>=A));then
printf ' %3d |' $(($A*$B))
else
printf ' |'
fi
done
printf ' %3d\n' $(($A*$B))
((A++))
done

© Copyright 2019 AJC formation - Sébastien Huss


Exercices 27/30
Information sur un utilisateur

Faire un script qui af che ceci


$ ./userinfo.sh seb
utilisateur : seb
UID : 1000
groupe : seb
groupes : cdrom floppy audio dip video plugdev netdev bluetooth lpadmin kvm libvirt lib

$ ./userinfo.sh root
utilisateur : root
UID : 0
groupe : root
groupes :

© Copyright 2019 AJC formation - Sébastien Huss


Exercices 28/30
Solution

#!/bin/bash affiche() {
aide() { printf '%16s : %s\n' "$1" "$2"
cat <<END }
$0 <username>
Affiche des informations sur un utilisateur # Corps du code
END if [ $# -ne 1 ];then
} echo "$0 requiere un argument" >&2
aide
# fonctions sur /etc/paswd exit 1
user_exist() { fi
awk -v u="$1" -v f=1 -F: '$1==u{f=0}END{exit f}'</etc/passwd case "$1" in
} -h|--help)
passwd_field() { aide;
awk -v u="$1" -F: '$1==u{print $'$2'}'</etc/passwd exit 0;;
} esac
user_id() { if ! user_exist "$1";then
passwd_field "$1" 3 echo "$1 n'existe pas" >&2
} aide
user_group() { exit 2
passwd_field "$1" 4 fi
}
affiche "utilisateur" "$1"
# fonctions sur /etc/group affiche "UID" "$(user_id "$1")"
group_name() { affiche "groupe" "$(group_name $(user_group "$1") )"
awk -v i="$1" -F: '$3==i{print $1}'</etc/group affiche "groupes" "$(user_groups "$1")"
}
user_groups_list() {
awk -F: -v u="$1" '$4~u{print $1}'</etc/group
}

# fonctions d'affichage
user_groups() {
local A=$(user_groups_list "$1")
echo $A
}

© Copyright 2019 AJC formation - Sébastien Huss


Exercices 29/30
index.html

Réaliser un script qui génère un chier index.html pour un répertoire


donné pour les chiers jpg, png et html
On pourra utiliser stat -c %y pour la date et du pour la taille
<html>
<head><title>Index de /home/seb/projects/formations/ajc</title></head>
<body>
<h1>Index de /home/seb/projects/formations/ajc</h1>
<hr/>
<table>
<tr><th>Type</th><th>Nom</th><th>Taille</th><th>Date de modification</th></tr>
<tr><td>dir</td><td>embarque_3</td><td></td><td>2019-02-09 12:05:54</td></tr>
<tr><td>html</td><td>embarque_1_presentation_unix.html</td><td>28K</td><td>2019-02-07 23:39:1
<tr><td>html</td><td>embarque_2_commande_linux.html</td><td>40K</td><td>2019-02-08 22:48:16</
<tr><td>html</td><td>embarque_3_scripts_shell.html</td><td>36K</td><td>2019-02-09 12:04:03</t
</table>
</body>
</html>

© Copyright 2019 AJC formation - Sébastien Huss


Exercices 30/30
Solution

#!/bin/bash {
cat <<END
list_files() { <html>
local D=${1:-'.'} <head><title>Index de ${CIBLE}</title></head>
ls -1 $D/*jpg $D/*png $D/*html 2>/dev/ <body><h1>Index de ${CIBLE}</h1><hr/>
} <table>
list_dir() { <tr><th>Type</th><th>Nom</th><th>Taille</th>
local D=${1:-'.'} <th>Date de modification</th></tr>
local i END
for i in $D/*;do for d in $(list_dir "$CIBLE");do
[ -d "$i" ] && echo $i echo "<tr><td>dir</td><td>$(basename "$
done echo "<td></td><td>$(mtime "$d")</td></
} done
mtime() { for f in $(list_files "$CIBLE");do
stat -c %y "$1"|sed 's/\..*//' cat <<END
} <tr><td>$(ext "$f")</td><td>$(basename "$f")</t
sz() { <td>$(sz "$f")</td><td>$(mtime "$f")</td></tr>
du -sh "$1"|awk '{print $1}' END
} done
ext() { cat <<END
echo ${1##*.} </table>
} </body></html>
END
CIBLE=${1:-"$PWD"} }>${CIBLE}/index.html

© Copyright 2019 AJC formation - Sébastien Huss

Vous aimerez peut-être aussi