BASH - Mémo pour scripter
Table des matières
Je script, je script, mais parfois, j'ai un sacré trou de mémoire ... et je galère à trouver ce que je cherche sur Internet.
Comment on incrémente une variable ? Comment on fait un SI, un POUR ?
Et bien la réponse se trouve ci-dessous !
Comme tout script BASH, le doit posséder son SHEBANG :
Pour mettre dans la variable a la valeur chaîne abcdefghijklmnopqrstuvwxyz :
De la même façon, on peut mettre dans des variables des nombres :
On peut mettre dans une variable le résultat d'une commande shell en encadrant la commande dans $() :
On pourra veiller à déclarer correctement les variables avec la commande declare pour forcer le type :
On peut faire du 2 en 1 évidemment : déclarer et affecter
Si vous voulez demander à l'utilisateur de taper du texte, et de récupérer le contenu dans une variable, c'est possible. C'est la commande read :
Ici, stockons le résultat de la saisie dans la variable TEXTE :
Avec l'option -p on pourra même mettre un message avant la saisie (qui se sera pas inclus dans le contenu de la variable) :
Il est possible de définir une valeur par défaut à la variable si celle-ci est vide ou non définie :
Si la variable choix a déjà une valeur, alors l'expression reste inchangée, et la valeur de choix reste la même.
Si la variable choix est vide ou non définie, alors elle est assignée à la valeur "N".
Pour utiliser ces variables, ajouter un $ devant. Exemple pour afficher la variable a :
On peut l'appeler en l'encadrant avec ${} :
On peut aussi afficher la longueur de cette variable avec ${#var} :
On peut aussi extraire une sous-chaine à la volée
Depuis une position (première position à 0) jusqu'à la fin :
Depuis une position avec une longueur :
Exemple pour afficher 6 caractères de la variable a en commençant au caractère 0 (début) :
Exemple pour afficher à partir du caractère 0 mais en retirant les 4 derniers caractères :
On peut aussi faire de la substitution directement dans la variable (sans passer par sed par exemple) :
Exemple, remplacer le "e" par "E" :
Si on veut que cela se fasse de manière globale (comme le /g de sed), on écrira 2 barres obliques :
On pourra aussi modifier la casse.
Forcer en MAJUSCULES :
Forcer en minuscules :
Il existe quelques variables spéciales :
$$ : PID du shell courant
$! : PID du dernier travail lancé en arrière plan
$? : code retour de la dernière commande
Et d'autres variables prédéfinies, dites variables d'environnement :
$HOME chemin du répertoire personnel de l'utilisateur
$OLDPWD chemin du répertoire précédent
$PATH liste des chemins de recherche des commandes exécutables
$PPID PID du processus père du shell
$PS1 invite principale du shell
$PWD chemin du répertoire courant
$RANDOM nombre entier aléatoire compris entre 0 et 32767
$REPLY variable par défaut de la commande "read" et de la structure shell "select"
$SECONDS nombre de secondes écoulées depuis le lancement du shell
Grosso-modo, pour faire des calculs simples, on utilise la syntaxe suivante :
On peut affecter ce calcul à une variable :
Ou bien l'afficher :
Si on veut faire une addition :
Si on veut faire une soustraction :
Si on veut faire une multiplication :
Si on veut faire une division :
On peut évidemment utiliser des variables dans le calcul :
Pour incrémenter ou décrémenter, on peut utiliser la fonction let :
Le test "Si'" est généralement fait ainsi :
Pour les exemples, nous avons besoin d'opérateurs de comparaison, voir ci-dessous.
En BASH, il y a deux possibilités pour écrire des tests :
et
La principale différence entre les deux est que le test avec le double crochet [[ ... ]] est propre à BASH et est une amélioration du simple crochet [ ... ], offrant des fonctionnalités supplémentaires telles que la manipulation de chaines avancées telles que les expressions régulières, ainsi que la possibilité d'utiliser des opérateurs logiques tels que && et ||.
Si on cherche à comparer simplement des nombres ou des chaînes le résultat est le même.
Par conséquent, j'utilise systématiquement le double crochet [[ ... ]].
-eq : est égal à
-ne : n'est pas égal à
-gt : est plus grand que
-ge : est plus grand ou égal à
-lt : est plus petit que
-le : est plus petit ou égal à
= : est égal à
!= : n'est pas égal à
-z string : Vrai si la longueur de la chaîne est égale à 0 (variable non initialisée ou vide)
-n string : Vrai si la longueur de la chaîne est supérieure à zero (variable initialisée et non vide)
=~ : match avec une regexp.
Exemple, si la variable contient "cou" :
Exemple, si ça commence par un a :
-z $var : Vrai si la taille de la chaîne est zéro (variable non utilisée ou vide)
-n $var : Vrai si la taille de la chaîne est différente de zéro (variable utilisée et non vide)
-e file : Vrai si le fichier existe
-d file : Vrai si le fichier existe et que c'est un répertoire
-f file : Vrai si le fichier existe et que c'est un fichier ordinaire
-h file : Vrai si le fichier existe et que c'est un lien symbolique
-r file : Vrai si le fichier possède les droits de lecture
-s file : Vrai si le fichier a une taille non nulle
-w file : Vrai si le fichier possède les droits d'écriture
-x file : Vrai si le fichier possède les droits d'exécution
-O file : Vrai si le possesseur est identique à celui qui exécute le test
-G file : Vrai si le possesseur qui exécute le test fait partie du groupe du fichier
-N file : Vrai si le fichier existe et qu'il a été modifié depuis sa dernière lecture
file1 -nt file2 : Vrai si le file1 est plus récent que file2 (date de modification) ou si file1 existe et pas file2
file1 -ot file2 : Vrai si file1 est plus ancien que file2 ou que file2 existe et pas file1
Le symbole de négation est !.
Si on teste de cette façon su un dossier existe :
Et bien tester s'il existe pas se fera ainsi :
Si vous voulez combiner des tests (le ET ou bien le OU) c'est avec && et || :
Pour le ET :
Pour le OU :
Pour le for ce n'est pas très compliqué :
On peut traiter avec une commande aussi, par exemple la boucle ci-dessus peut être écrite en utilisant la commande seq :
Et on peut aussi utiliser des chaines de caractère :
Pour la boucle infinie, utiliser ceci (fin de la boucle avec break) ou CTRL+C :
De manière générale, la syntaxe est la suivante :
Voici un exemple :
La boucle infinie se traduit ainsi :
La boucle infinie peut s’interrompre avec break :
Le case (ou parfois dans d'autres langages switch) permet d'éviter l'imbrication de multiples if.
Voici un exemple. Le test peut être fait sur une chaine (ici B KB MB GB TB) ou sur des nombres :
Il est possible d'utiliser les tableaux en bash !
Affectation du premier enregistrement du tableau "tab" :
Contenu du premier enregistrement du tableau "tab" :
ou
Contenu du douzième enregistrement du tableau "tab" (oui ça commence à 0) :
Ensemble des enregistrements du tableau "tab" :
Longueur du douzième enregistrement du tableau "tab" :
Nombre d'enregistrements du tableau "tab" :
Pour lire les lignes d'un fichier :
Si on veut lire un fichier avec des lignes avec un séparateur (exemple passwd, qui a le séparateur : ) on peut stocker direct dans les variables
Pour vérifier si le script est lancé en root, on peut utiliser ce petit morceau de code qui va vérifier l'id de l'utilisateur (0 = root) :
Tous se passe dans le code retour de la commande.
Exemple avec ls. La page man indique les différents codes retour :
Ce code est stocké dans la variable $? :
Voyons un exemple avec un succès (même si je n'ai rien dans /mnt, la commande n'a rencontré aucune erreur, le code vaut donc 0) :
Ici un exemple avec un répertoire inexistant (le code vaut 2) :
On peut tester le bon fonctionnement d'une commande en testant cette valeur retour :
La variable $? est modifiée à chaque exécution d'une commande.
On peut faire le test différemment ainsi :
Pour agrémenter vos scripts, vous pouvez mettre de la couleur.
Voici une liste des couleurs possibles (ici j'affecte à des variables les codes couleur) :
Dans un code de type \033[0;31m pour le rouge, vous pouvez remplacer le 0 après le crochet ouvrant indique le style du texte.
0 : Standard
1 : Gras
2 : Ca semble plus foncé
3 : Italique
4 : Souligné
5 : Clignotant
7 : Surligné
9 : Barré
Voici un exemple en rouge et gras (notez l'usage de l'option -e de echo) :
Introduction
Je script, je script, mais parfois, j'ai un sacré trou de mémoire ... et je galère à trouver ce que je cherche sur Internet.
Comment on incrémente une variable ? Comment on fait un SI, un POUR ?
Et bien la réponse se trouve ci-dessous !
Prérequis
Comme tout script BASH, le doit posséder son SHEBANG :
Code BASH :
#!/bin/bash
Les variables
Affectation de variable
Pour mettre dans la variable a la valeur chaîne abcdefghijklmnopqrstuvwxyz :
Code BASH :
a="abcdefghijklmnopqrstuvwxyz"
De la même façon, on peut mettre dans des variables des nombres :
Code BASH :
b=2
On peut mettre dans une variable le résultat d'une commande shell en encadrant la commande dans $() :
Code BASH :
nb=$(ls -l /etc | wc -l)
On pourra veiller à déclarer correctement les variables avec la commande declare pour forcer le type :
Code BASH :
declare -r variableEnLectureSeule declare -i entier declare -a tableau
On peut faire du 2 en 1 évidemment : déclarer et affecter
Code BASH :
declare -i nb=42
Lire une variable depuis une saisie du clavier
Si vous voulez demander à l'utilisateur de taper du texte, et de récupérer le contenu dans une variable, c'est possible. C'est la commande read :
Ici, stockons le résultat de la saisie dans la variable TEXTE :
Code BASH :
read TEXTE
Avec l'option -p on pourra même mettre un message avant la saisie (qui se sera pas inclus dans le contenu de la variable) :
Code BASH :
read -p "Saisir un mot : " TEXTE
Définir une valeur par défaut à une variable
Il est possible de définir une valeur par défaut à la variable si celle-ci est vide ou non définie :
Code BASH :
choix=${choix:-N}
Si la variable choix a déjà une valeur, alors l'expression reste inchangée, et la valeur de choix reste la même.
Si la variable choix est vide ou non définie, alors elle est assignée à la valeur "N".
Utiliser les variables
Pour utiliser ces variables, ajouter un $ devant. Exemple pour afficher la variable a :
Code BASH :
echo $a
On peut l'appeler en l'encadrant avec ${} :
Code BASH :
echo ${a}
On peut aussi afficher la longueur de cette variable avec ${#var} :
Code TEXT :
echo ${#a}
Utilisation avancée
On peut aussi extraire une sous-chaine à la volée
Depuis une position (première position à 0) jusqu'à la fin :
Code BASH :
echo ${VAR:position}
Depuis une position avec une longueur :
Code BASH :
echo ${VAR:position:longueur}
Exemple pour afficher 6 caractères de la variable a en commençant au caractère 0 (début) :
Code BASH :
echo ${a:0:6}
Exemple pour afficher à partir du caractère 0 mais en retirant les 4 derniers caractères :
Code BASH :
echo ${a:0:-4}
On peut aussi faire de la substitution directement dans la variable (sans passer par sed par exemple) :
Code BASH :
echo ${VAR/cherche/remplace}
Exemple, remplacer le "e" par "E" :
Code BASH :
echo ${VAR/e/E}
Si on veut que cela se fasse de manière globale (comme le /g de sed), on écrira 2 barres obliques :
Code BASH :
echo ${VAR//cherche/remplace}
On pourra aussi modifier la casse.
Forcer en MAJUSCULES :
Code BASH :
echo ${VAR^^}
Forcer en minuscules :
Code BASH :
echo ${VAR,,}
Variables spéciales
Il existe quelques variables spéciales :
$$ : PID du shell courant
$! : PID du dernier travail lancé en arrière plan
$? : code retour de la dernière commande
Et d'autres variables prédéfinies, dites variables d'environnement :
$HOME chemin du répertoire personnel de l'utilisateur
$OLDPWD chemin du répertoire précédent
$PATH liste des chemins de recherche des commandes exécutables
$PPID PID du processus père du shell
$PS1 invite principale du shell
$PWD chemin du répertoire courant
$RANDOM nombre entier aléatoire compris entre 0 et 32767
$REPLY variable par défaut de la commande "read" et de la structure shell "select"
$SECONDS nombre de secondes écoulées depuis le lancement du shell
Calculs
Calculs simples
Grosso-modo, pour faire des calculs simples, on utilise la syntaxe suivante :
Code BASH :
$((calcul))
On peut affecter ce calcul à une variable :
Code BASH :
a=$((calcul))
Ou bien l'afficher :
Code BASH :
echo $((calcul))
Si on veut faire une addition :
Code BASH :
echo $((21+21)) 42
Si on veut faire une soustraction :
Code BASH :
echo $((63-21)) 42
Si on veut faire une multiplication :
Code BASH :
echo $((2*21)) 42
Si on veut faire une division :
Code BASH :
echo $((84/2)) 42
On peut évidemment utiliser des variables dans le calcul :
Code BASH :
i=42 echo $(($i*2)) 84
Incrémenter et décrémenter
Pour incrémenter ou décrémenter, on peut utiliser la fonction let :
Code BASH :
i=42 let i-- echo $i 41
Code BASH :
let i++ echo $i 42
Les structures conditionnelles : If
Le test "Si'" est généralement fait ainsi :
Code BASH :
if [[ condition ]] then commande 1 commande2 fi
Pour les exemples, nous avons besoin d'opérateurs de comparaison, voir ci-dessous.
A propos de la syntaxe des tests
En BASH, il y a deux possibilités pour écrire des tests :
Code BASH :
[ test ]
et
Code BASH :
[[ test ]]
La principale différence entre les deux est que le test avec le double crochet [[ ... ]] est propre à BASH et est une amélioration du simple crochet [ ... ], offrant des fonctionnalités supplémentaires telles que la manipulation de chaines avancées telles que les expressions régulières, ainsi que la possibilité d'utiliser des opérateurs logiques tels que && et ||.
Si on cherche à comparer simplement des nombres ou des chaînes le résultat est le même.
Par conséquent, j'utilise systématiquement le double crochet [[ ... ]].
Les opérateurs de comparaison
Comparaison d'entiers
-eq : est égal à
Code BASH :
if [[ "$a" -eq "$b" ]]
-ne : n'est pas égal à
Code BASH :
if [[ "$a" -ne "$b" ]]
-gt : est plus grand que
Code BASH :
if [[ "$a" -gt "$b" ]]
-ge : est plus grand ou égal à
Code BASH :
if [[ "$a" -ge "$b" ]]
-lt : est plus petit que
Code BASH :
if [[ "$a" -lt "$b" ]]
-le : est plus petit ou égal à
Code BASH :
if [[ "$a" -le "$b" ]]
Comparaison de chaînes
= : est égal à
Code BASH :
if [[ "$a" = "$b" ]]
!= : n'est pas égal à
Code BASH :
if [[ "$a" != "$b" ]]
-z string : Vrai si la longueur de la chaîne est égale à 0 (variable non initialisée ou vide)
Code BASH :
if [[ -z "$var" ]]
-n string : Vrai si la longueur de la chaîne est supérieure à zero (variable initialisée et non vide)
Code BASH :
if [[ -n "$var" ]]
Match de chaine
=~ : match avec une regexp.
Exemple, si la variable contient "cou" :
Code BASH :
if [[ "$a" =~ cou ]]
Exemple, si ça commence par un a :
Code BASH :
if [[ "$a" =~ ^a ]]
Les tests sur les chaines
-z $var : Vrai si la taille de la chaîne est zéro (variable non utilisée ou vide)
Code BASH :
if [[ -z $var ]]
-n $var : Vrai si la taille de la chaîne est différente de zéro (variable utilisée et non vide)
Code BASH :
if [[ -n $var ]]
Les tests sur les fichiers
-e file : Vrai si le fichier existe
Code BASH :
if [[ -e /tmp/fichier ]]
-d file : Vrai si le fichier existe et que c'est un répertoire
Code BASH :
if [[ -d /tmp/dossier ]]
-f file : Vrai si le fichier existe et que c'est un fichier ordinaire
Code BASH :
if [[ -f /tmp/fichier ]]
-h file : Vrai si le fichier existe et que c'est un lien symbolique
Code BASH :
if [[ -h /tmp/lien ]]
-r file : Vrai si le fichier possède les droits de lecture
Code BASH :
if [[ -r /tmp/fichier ]]
-s file : Vrai si le fichier a une taille non nulle
Code BASH :
if [[ -s /tmp/fichier ]]
-w file : Vrai si le fichier possède les droits d'écriture
Code BASH :
if [[ -w /tmp/fichier ]]
-x file : Vrai si le fichier possède les droits d'exécution
Code BASH :
if [[ -x /tmp/fichier ]]
-O file : Vrai si le possesseur est identique à celui qui exécute le test
Code BASH :
if [[ -O /tmp/fichier ]]
-G file : Vrai si le possesseur qui exécute le test fait partie du groupe du fichier
Code BASH :
if [[ -G /tmp/fichier ]]
-N file : Vrai si le fichier existe et qu'il a été modifié depuis sa dernière lecture
Code BASH :
if [[ -N /tmp/fichier ]]
Comparaison de fichiers
file1 -nt file2 : Vrai si le file1 est plus récent que file2 (date de modification) ou si file1 existe et pas file2
Code BASH :
if [[ file1 -nt file2 ]]
file1 -ot file2 : Vrai si file1 est plus ancien que file2 ou que file2 existe et pas file1
Code BASH :
if [[ file1 -ot file2 ]]
La négation (inverser le test)
Le symbole de négation est !.
Si on teste de cette façon su un dossier existe :
Code BASH :
if [[ -d "$DIR" ]]
Et bien tester s'il existe pas se fera ainsi :
Code BASH :
if [[ ! -d "$DIR" ]]
Et Ou
Si vous voulez combiner des tests (le ET ou bien le OU) c'est avec && et || :
Pour le ET :
Code BASH :
if [[ "$a" -gt "$b" && "$c" -gt "$d" ]]
Pour le OU :
Code BASH :
if [[ "$a" -gt "$b" || "$c" -gt "$d" ]]
Les structures conditionnelles Partie 2
For
Pour le for ce n'est pas très compliqué :
Code BASH :
for i in 1 2 3 4 5 do echo $i commande1 commande2 commandeN done
On peut traiter avec une commande aussi, par exemple la boucle ci-dessus peut être écrite en utilisant la commande seq :
Code BASH :
for i in $(seq 1 5) do echo $i commande1 commande2 commandeN done
Et on peut aussi utiliser des chaines de caractère :
Code BASH :
for f in fic1 fic2 fic3 do echo "On affiche le fichier $f" cat $f done
Pour la boucle infinie, utiliser ceci (fin de la boucle avec break) ou CTRL+C :
Code BASH :
for (( ; ; )) do echo "boucle infinie" done
While
De manière générale, la syntaxe est la suivante :
Code BASH :
while [[ condition ]] do commande1 commande2 commande3 done
Voici un exemple :
Code BASH :
x=1 while [[ "$x" -le 5 ]] do echo "Passage numéro $i" x=$(($x+1)) done
La boucle infinie se traduit ainsi :
Code BASH :
while : do echo "boucle infinie" done
La boucle infinie peut s’interrompre avec break :
Code BASH :
while : do read -p "Entrer un chiffre ( -1 pour quitter ) : " a if [[ "$a" -eq -1 ]] then break fi echo "Vous avez saisi $a" done
Case ou switch
Le case (ou parfois dans d'autres langages switch) permet d'éviter l'imbrication de multiples if.
Voici un exemple. Le test peut être fait sur une chaine (ici B KB MB GB TB) ou sur des nombres :
Code BASH :
case $UNIT in B) echo "Unité Octet" ;; KB) echo "Unité KiloOctet" ;; MB) echo "Unité MegaOctet" ;; GB) echo "Unité GigaOctet" ;; TB) echo "Unité TeraOctet" ;; *) echo "Choix par défaut" ;; esac
Les tableaux
Il est possible d'utiliser les tableaux en bash !
Affectation du premier enregistrement du tableau "tab" :
Code BASH :
tab[0]=val
Contenu du premier enregistrement du tableau "tab" :
Code BASH :
echo ${tab[0]}
ou
Code BASH :
echo $tab
Contenu du douzième enregistrement du tableau "tab" (oui ça commence à 0) :
Code BASH :
echo ${tab[11]}
Ensemble des enregistrements du tableau "tab" :
Code BASH :
echo ${tab[*]}
Longueur du douzième enregistrement du tableau "tab" :
Code BASH :
echo ${#tab[11]}
Nombre d'enregistrements du tableau "tab" :
Code BASH :
echo ${#tab[*]}
Des petits trucs marrants
Lire un fichier ligne par ligne
Pour lire les lignes d'un fichier :
Code BASH :
while read ligne do echo "$ligne" done < fichier
Si on veut lire un fichier avec des lignes avec un séparateur (exemple passwd, qui a le séparateur : ) on peut stocker direct dans les variables
Code BASH :
while IFS=: read user pass uid gid nom dossperso shell do echo "$user avec UID $uid a son home dans $dossperso" done < /etc/passwd
Vérifier si on est root
Pour vérifier si le script est lancé en root, on peut utiliser ce petit morceau de code qui va vérifier l'id de l'utilisateur (0 = root) :
Code BASH :
if [[ $(id -u) -ne 0 ]] then echo "Doit être lancé en root" exit 1 fi
Vérifier le bon déroulement d'une commande
Tous se passe dans le code retour de la commande.
Exemple avec ls. La page man indique les différents codes retour :
Code TEXT :
0 si OK, 1 si problèmes mineurs (par exemple, impossible d'accéder à un sous-répertoire), 2 si erreur grave (par exemple, impossible d'accéder aux pa‐ ramètres de la ligne de commande).
Ce code est stocké dans la variable $? :
Voyons un exemple avec un succès (même si je n'ai rien dans /mnt, la commande n'a rencontré aucune erreur, le code vaut donc 0) :
Code BASH :
ls /mnt echo $? 0
Ici un exemple avec un répertoire inexistant (le code vaut 2) :
Code BASH :
ls /existepas ls: impossible d'accéder à '/existepas': Aucun fichier ou dossier de ce type echo $? 2
On peut tester le bon fonctionnement d'une commande en testant cette valeur retour :
Code BASH :
ls /mondossier if [[ "$?" -ne "0" ]] then echo "Dossier introuvable" fi
La variable $? est modifiée à chaque exécution d'une commande.
On peut faire le test différemment ainsi :
Code BASH :
if ! ls /mondossier; then echo "Dossier introuvable" fi
Mettre le texte en couleur
Pour agrémenter vos scripts, vous pouvez mettre de la couleur.
Voici une liste des couleurs possibles (ici j'affecte à des variables les codes couleur) :
Code BASH :
# Réinitialisation de la couleur après cette balise COLOR_RESET='\033[0m' # Codes couleurs à placer avant le texte : COLOR_NOIR='\033[0;30m' COLOR_ROUGE='\033[0;31m' COLOR_VERT='\033[0;32m' COLOR_JAUNE='\033[0;33m' COLOR_BLEU='\033[0;34m' COLOR_VIOLET='\033[0;35m' COLOR_CYAN='\033[0;36m' COLOR_BLANC='\033[0;37m'
Dans un code de type \033[0;31m pour le rouge, vous pouvez remplacer le 0 après le crochet ouvrant indique le style du texte.
0 : Standard
1 : Gras
2 : Ca semble plus foncé
3 : Italique
4 : Souligné
5 : Clignotant
7 : Surligné
9 : Barré
Voici un exemple en rouge et gras (notez l'usage de l'option -e de echo) :
Code BASH :
echo -e '\033[1;31m' ROUGE '\033[0m'