diff --git a/Scripting/Bash.html b/Scripting/Bash.html index ced340b..c4d3a21 100644 --- a/Scripting/Bash.html +++ b/Scripting/Bash.html @@ -2,7 +2,7 @@ title: Scripting - Bash description: Les bases de l'automatisation ! published: true -date: 2021-05-17T09:15:56.027Z +date: 2021-05-17T09:30:30.816Z tags: editor: ckeditor dateCreated: 2021-05-17T08:41:21.766Z @@ -324,6 +324,101 @@ $ set “Bonjour à tous” $ echo ${#1} 14 $ ls > /dev/null -$ $ echo ${#?} -1 #=> la longueur du code de retour (0) est de 1 caractère
On peut modifier les chaîne de caractères directement :
Syntaxe : ${paramètre#modèle} pour supprimer la plus courte sous-chaîne à gauche
Exemple :
1
$ echo $PWD
2
/home/christophe
3
$ echo ${PWD#*/}
4
home/christophe #=> le premier caractère / a été supprimé
5
$
6
$ set “25b75b”
7
$
8
$ echo ${1#*b}
9
75b #=> Suppression de la sous-chaîne 25b
Syntaxe: ${paramètre##modèle}
pour supprimer la plus longue sous-chaîne à gauche
Exemple :
1
$ echo $PWD
2
/home/christophe
3
$ echo ${PWD##*/}
4
christophe #=> suppression jusqu’au dernier caractère /
5
$
6
$ set “25b75b”
7
$
8
$ echo ${1##*b}
9
b
Pour la suppression par la droite, c’est la même chose en utilise le caractère % comme contrôle
Syntaxe :${paramètre%modèle}
pour supprimer la plus courte sous-chaîne à droite${paramètre%%modèle}
pour supprimer la plus longue sous-chaîne à droite
On peut extraire une sous-chaîne également :
Syntaxe:${paramètre:ind}
: extrait la valeur de paramètre de la sous-chaîne débutant à l’indice ind.${paramètre:ind:nb}
: extrait nb caractères à partir de l’indice ind
Exemple :
1
$ lettres=”abcdefghijklmnopqrstuvwxyz”
2
$
3
$ echo {$lettre:20}
4
uvwxyz
5
$ echo {$lettre:3:4}
6
defg
7
$
Remplacement dans une sous-chaîne
Syntaxe:${paramètre/mod/ch}
bash recherchera dans paramètre la plus longue sous-chaîne satisfaisant le modèle mod puis remplacera cette sous-chaîne par
la chaîne ch. Seule la première sous-chaîne trouvée sera remplacée. mod peut être des caractères ou expressions génériques.${paramètre//mod/ch}
:
Pour replacer toutes les occurrences et pas seulement la première${paramètre/mod/}
:${paramètre//mod/}
:
Supprime au lieu de remplacer
Exemple :
1
$ v=totito
2
$ echo {$v/to/lo}
3
lotito
4
$ echo {$v//to/lo}
5
lotilo
Syntaxe 1:
1
for var
2
do
3
suite_de_commandes
4
done
5
Syntaxe 2:
6
for var in liste_mots
7
do
8
suite_de_commandes
9
done
Dans la première forme, la variable var prend successivement la valeur de chaque paramètre de position initialisé
Exemple :
1
$ cat for_args.sh
2
#!/bin/bash
3
for i
4
do
5
echo $i
6
echo “next ...”
7
done
8
9
$ ./for_args.sh first second third
10
first
11
next ...
12
second
13
next ...
14
third
15
next ...
Exemple 2:
1
$ cat for_set.sh
2
#!/bin/bash
3
set $(date)
4
for i
5
do
6
echo $i
7
done
8
9
$ ./for_set.sh
10
samedi
11
29
12
Juin
13
2019,
14
12:09:21
15
(UTC+0200)
16
$
La deuxième syntaxe permet à var de prendre successivement la valeur de chaque mot de liste_mots.
Exemple :
1
$ cat for_liste.sh
2
#!/bin/bash
3
for a in toto tata
4
do
5
echo $a
6
done
Si liste_mots contient des substitutions, elles sont préalablement traitées par bash
Exemple 2:
1
$ cat affiche_ls.sh
2
#!/bin/bash
3
for i in /tmp ${pwd}
4
do
5
echo “ --- $i ---”
6
ls $i
7
done
8
9
$ ./affiche_ls.sh
10
--- /tmp ---
11
toto tutu
12
--- /home/christophe
13
for_liste.sh affiche_ls.sh alpha tmp
La commande interne if implante le choix alternatif
Syntaxe :
1
if suite_commande1
2
then
3
suite_commande2
4
[elif suite_de_commandes; then suite_de_commande] ...
5
[else suite_de_commandes]
6
fi
Le principe de fonctionnement est le même que pour le for, on test la valeur de retour d’une commande plutôt qu’une valeur booléenne simple. Donc dans notre exemple, suite_commande2 est exécuté, si suite_commande1 renvoi 0 (pas d’erreur). Sinon c’est elif ou bien else qui sera exécuté.
Exemple :
1
$ cat rm1.sh
2
#!/bin/bash
3
if rm “$1” 2> /dev/null
4
then echo $1 a été supprimé
5
else echo $1 n\’a pas été supprimé
6
fi
7
8
$ >toto
9
$ rm1 toto
10
toto a été supprimé
11
$
12
$ rm1 toto
13
toto n’a pas été supprimé
14
$
Lorsque rm1 toto est lancé, si le fichier toto est effaçable, il le sera, et la commande rm renvoi 0.
Notez qu’il est possible d’imbriquer les if ensembles
Exemple :
1
if...
2
then....
3
if...
4
then ...
5
fi
6
else ...
7
fi
Dans les bash, vous retrouverez souvent une notation de commande interne [[ souvent utilisé avec le if. Elle permet l’évaluation de d’expressions conditionnelles portant sur des objets aussi différents que les permissions sur une entrée, la valeur d’une chaîne de caractères ou encore l’état d’une option de la commande interne set.
Syntaxe: [[ expr_conditionelle ]]
Les deux caractères crochets doivent être collés et un caractère séparateur doit être présent de part et d’autre de expr_conditionelle. Les mots [[ et ]] sont des mots-clés. On a vu que le if fonctionne selon la valeur de retour d’une commande, et pas d’un booléen, cette syntaxe permet “d'exécuter un test” qui renverra 1 si le test est vrai, 0 sinon. Si l’expression contient des erreurs syntaxique une autre valeur sera retournée. La commande interne [[ offre de nombreuses expressions conditionnelles, c’est pourquoi seules les principales formes de exp_conditionnelle seront présentées, regroupées par catégories.
-r entrée vraie si entrée existe et est accessible en lecture par le processus courant
-w entrée vraie si entrée existe et est accessible en écriture par le processus courant
-x entrée vraie si entrée existe et est accessible en exécutable par le processus courant ou si le répertoire entrée existe et
le processus courant possède la permission de passage
Exemple :
1
$ echo coucou > toto
2
$ chmod 200 toto
3
$ ls -l toto
4
--w- --- --- 1 christophe christophe 29 juin 1 14:04 toto
5
$
6
$ if [[ -r toto ]]
7
> then cat toto
8
> fi
9
$ => rien ne ce passe
10
$ echo $?
11
0 => code de retour de la commande interne if
12
$
13
MAIS
14
$ [[ -r toto ]]
15
$ echo $?
16
1 => code de retour de la commande interne [[
17
$
-f entrée vraie si entrée existe et est un fichier ordinaire
-d entrée vraie si entrée existe et est un répertoire
Exemple :
1
$ cat afficher.sh
2
#!/bin/bash
3
if [[ -f “$1” ]]
4
then
5
echo “$1” : fichier ordinaire
6
cat “$1”
7
elif [[ -d “$1” ]]
8
then
9
echo “$1” : répertoire
10
ls “$1”
11
else
12
echo “$1” : type non traité
13
fi
14
15
$ ./afficher
16
. : répertoire
17
afficher.sh test.sh toto alpha rm1.sh
18
$
Renseignement divers sur une entrée
-a entrée vraie si entrée existe
-s entrée vraie si entrée existe et sa taille est différente de 0 (un répertoire vide > 0)
entrée 1 -nt entrée 2 vraie si entrée 1 existe et sa date de modification est plus récente que celle de entrée2
entrée1 -ot entrée 2 vraie si entrée1 existe et sa date de modification est plus ancienne que celle de entrée2
Exemple :
1
$ > err
2
$
3
$ ls -l err
4
-rw-rw-r-- 1 christophe christophe 0 juin 29 14:30 err
5
$ if [[ -a err ]]
6
> then echo err existe
7
> fi
8
err existe
9
$ if [[ -s err ]]
10
> then echo err n’est pas vide
11
> else err est vide
12
> fi
13
err est vide
14
$
-Z ch vraie si la longueur de ch est égale à 0
ch ou (-n ch) vraie si la longueur de ch est différente de 0
ch1 < ch2 vraie si ch1 précède ch2
ch1 > ch2 vraie si ch1 suit ch2
ch == mod vraie si la chaîne ch correspond au modèle mod
ch != mod vraie si la chaîne ch ne correspond pas au modèle mod
-o opt vraie si l’option interne opt est sur on
Important : il existe un opérateur =~ qui permet de mettre en correspondance une chaîne de caractères ch avec une expression
régulière.
Exemple :
1
$a=01/01/2010
2
$[[ $a =~ [0-9]{2}\/[0-9]{2}\/[0-9]{2,4} ]]
3
$ echo $?
4
0
5
$ a=45/54/1
6
$[[ $a =~ [0-9]{2}\/[0-9]{2}\/[0-9]{2,4} ]]
7
$ echo $?
8
1
( cond ) vraie si cond est vraie
! cond vraie si cond est fausse
cond1 && cond 2 vraie si cond1 et 2 sont vraie, l’évaluation s’arrête si cond1 est fausse
cond1 || cond2 vraie si cond1 ou 2 sont vraie.
Exemple :
1
$ ls -l /etc/at.deny
2
-rw-r----- 1 root daemon 144 oct. 25 2018 /etc/at.deny
3
$
4
$ if [[ ! ( -w /etc/at.deny || -r /etc/at.deny ) ]]
5
> then
6
> echo OUI
7
> else
8
> echo NON
9
> fi
10
OUI
+1 #=> la longueur du code de retour (0) est de 1 caractère
On peut modifier les chaîne de caractères directement :
Syntaxe : ${paramètre#modèle}
pour supprimer la plus courte sous-chaîne à gauche
Exemple :
$ echo $PWD
+/home/christophe
+$ echo ${PWD#*/}
+home/christophe #=> le premier caractère / a été supprimé
+$ set “25b75b”
+$ echo ${1#*b}
+75b #=> Suppression de la sous-chaîne 25b
Syntaxe: ${paramètre##modèle}
pour supprimer la plus longue sous-chaîne à gauche
Exemple :
$ echo $PWD
+/home/christophe
+$ echo ${PWD##*/}
+christophe #=> suppression jusqu’au dernier caractère /
+$ set “25b75b”
+$ echo ${1##*b}
+b
Pour la suppression par la droite, c’est la même chose en utilise le caractère % comme contrôle
Syntaxe :${paramètre%modèle}
pour supprimer la plus courte sous-chaîne à droite${paramètre%%modèle}
pour supprimer la plus longue sous-chaîne à droite
On peut extraire une sous-chaîne également :
Syntaxe:${paramètre:ind}
: extrait la valeur de paramètre de la sous-chaîne débutant à l’indice ind.${paramètre:ind:nb}
: extrait nb caractères à partir de l’indice ind
Exemple :
$ lettres=”abcdefghijklmnopqrstuvwxyz”
+$ echo {$lettre:20}
+uvwxyz
+$ echo {$lettre:3:4}
+defg
Remplacement dans une sous-chaîne
Syntaxe:${paramètre/mod/ch}
bash recherchera dans paramètre la plus longue sous-chaîne satisfaisant le modèle mod puis remplacera cette sous-chaîne par
la chaîne ch. Seule la première sous-chaîne trouvée sera remplacée. mod peut être des caractères ou expressions génériques.${paramètre//mod/ch}
: Pour replacer toutes les occurrences et pas seulement la première${paramètre/mod/}
:${paramètre//mod/}
: Supprime au lieu de remplacer
Exemple :
$ v=totito
+$ echo {$v/to/lo}
+lotito
+$ echo {$v//to/lo}
+lotilo
Syntaxe :
for var
+do
+suite_de_commandes
+done
+Syntaxe 2:
+for var in liste_mots
+do
+suite_de_commandes
+done
Dans la première forme, la variable var prend successivement la valeur de chaque paramètre de position initialisé
Exemple :
$ cat for_args.sh
+#!/bin/bash
+for i
+do
+echo $i
+echo “next ...”
+done
+
+$ ./for_args.sh first second third
+first
+next ...
+second
+next ...
+third
+next ...
Exemple 2 :
$ cat for_set.sh
+#!/bin/bash
+set $(date)
+for i
+do
+echo $i
+done
+
+$ ./for_set.sh
+samedi
+29
+Juin
+2019,
+12:09:21
+(UTC+0200)
La deuxième syntaxe permet à var de prendre successivement la valeur de chaque mot de liste_mots.
Exemple :
$ cat for_liste.sh
+#!/bin/bash
+for a in toto tata
+do
+echo $a
+done
Si liste_mots contient des substitutions, elles sont préalablement traitées par bash.
Exemple 2 :
$ cat affiche_ls.sh
+#!/bin/bash
+for i in /tmp ${pwd}
+do
+echo “ --- $i ---”
+ls $i
+done
+
+$ ./affiche_ls.sh
+--- /tmp ---
+toto tutu
+--- /home/christophe
+for_liste.sh affiche_ls.sh alpha tmp
La commande interne if implante le choix alternatif
Syntaxe :
if suite_commande1
+then
+suite_commande2
+[elif suite_de_commandes; then suite_de_commande] ...
+[else suite_de_commandes]
+fi
Le principe de fonctionnement est le même que pour le for
, on test la valeur de retour d’une commande plutôt qu’une valeur booléenne simple. Donc dans notre exemple, suite_commande2
est exécuté, si suite_commande1
renvoi 0
(pas d’erreur). Sinon c’est elif
ou bien else
qui sera exécuté.
Exemple :
$ cat rm1.sh
+#!/bin/bash
+if rm “$1” 2> /dev/null
+then echo $1 a été supprimé
+else echo $1 n\’a pas été supprimé
+fi
+
+$ >toto
+$ rm1 toto
+toto a été supprimé
+
+$ rm1 toto
+toto n’a pas été supprimé
Lorsque rm1 toto
est lancé, si le fichier toto
est effaçable, il le sera, et la commande rm
renvoi 0
.
Notez qu’il est possible d’imbriquer les if
ensembles.
Exemple :
if...
+ then....
+ if...
+ then ...
+ fi
+ else ...
+fi
Dans les bash, vous retrouverez souvent une notation de commande interne [[
souvent utilisé avec le if
. Elle permet l’évaluation de d’expressions conditionnelles portant sur des objets aussi différents que les permissions sur une entrée, la valeur d’une chaîne de caractères ou encore l’état d’une option de la commande interne set.
Syntaxe : [[ expr_conditionelle ]]
Les deux caractères crochets doivent être collés et un caractère séparateur doit être présent de part et d’autre de expr_conditionelle. Les mots [[ et ]] sont des mots-clés. On a vu que le if fonctionne selon la valeur de retour d’une commande, et pas d’un booléen, cette syntaxe permet “d'exécuter un test” qui renverra 1 si le test est vrai, 0 sinon. Si l’expression contient des erreurs syntaxique une autre valeur sera retournée. La commande interne [[ offre de nombreuses expressions conditionnelles, c’est pourquoi seules les principales formes de exp_conditionnelle seront présentées, regroupées par catégories.
-r entrée vraie si entrée existe et est accessible en lecture par le processus courant
-w entrée vraie si entrée existe et est accessible en écriture par le processus courant
-x entrée vraie si entrée existe et est accessible en exécutable par le processus courant ou si le répertoire entrée existe et
le processus courant possède la permission de passage
Exemple :
1
$ echo coucou > toto
2
$ chmod 200 toto
3
$ ls -l toto
4
--w- --- --- 1 christophe christophe 29 juin 1 14:04 toto
5
$
6
$ if [[ -r toto ]]
7
> then cat toto
8
> fi
9
$ => rien ne ce passe
10
$ echo $?
11
0 => code de retour de la commande interne if
12
$
13
MAIS
14
$ [[ -r toto ]]
15
$ echo $?
16
1 => code de retour de la commande interne [[
17
$
-f entrée vraie si entrée existe et est un fichier ordinaire
-d entrée vraie si entrée existe et est un répertoire
Exemple :
1
$ cat afficher.sh
2
#!/bin/bash
3
if [[ -f “$1” ]]
4
then
5
echo “$1” : fichier ordinaire
6
cat “$1”
7
elif [[ -d “$1” ]]
8
then
9
echo “$1” : répertoire
10
ls “$1”
11
else
12
echo “$1” : type non traité
13
fi
14
15
$ ./afficher
16
. : répertoire
17
afficher.sh test.sh toto alpha rm1.sh
18
$
Renseignement divers sur une entrée
-a entrée vraie si entrée existe
-s entrée vraie si entrée existe et sa taille est différente de 0 (un répertoire vide > 0)
entrée 1 -nt entrée 2 vraie si entrée 1 existe et sa date de modification est plus récente que celle de entrée2
entrée1 -ot entrée 2 vraie si entrée1 existe et sa date de modification est plus ancienne que celle de entrée2
Exemple :
1
$ > err
2
$
3
$ ls -l err
4
-rw-rw-r-- 1 christophe christophe 0 juin 29 14:30 err
5
$ if [[ -a err ]]
6
> then echo err existe
7
> fi
8
err existe
9
$ if [[ -s err ]]
10
> then echo err n’est pas vide
11
> else err est vide
12
> fi
13
err est vide
14
$
-Z ch vraie si la longueur de ch est égale à 0
ch ou (-n ch) vraie si la longueur de ch est différente de 0
ch1 < ch2 vraie si ch1 précède ch2
ch1 > ch2 vraie si ch1 suit ch2
ch == mod vraie si la chaîne ch correspond au modèle mod
ch != mod vraie si la chaîne ch ne correspond pas au modèle mod
-o opt vraie si l’option interne opt est sur on
Important : il existe un opérateur =~ qui permet de mettre en correspondance une chaîne de caractères ch avec une expression
régulière.
Exemple :
1
$a=01/01/2010
2
$[[ $a =~ [0-9]{2}\/[0-9]{2}\/[0-9]{2,4} ]]
3
$ echo $?
4
0
5
$ a=45/54/1
6
$[[ $a =~ [0-9]{2}\/[0-9]{2}\/[0-9]{2,4} ]]
7
$ echo $?
8
1
( cond ) vraie si cond est vraie
! cond vraie si cond est fausse
cond1 && cond 2 vraie si cond1 et 2 sont vraie, l’évaluation s’arrête si cond1 est fausse
cond1 || cond2 vraie si cond1 ou 2 sont vraie.
Exemple :
1
$ ls -l /etc/at.deny
2
-rw-r----- 1 root daemon 144 oct. 25 2018 /etc/at.deny
3
$
4
$ if [[ ! ( -w /etc/at.deny || -r /etc/at.deny ) ]]
5
> then
6
> echo OUI
7
> else
8
> echo NON
9
> fi
10
OUI