Mes notes pour scripts bash

Je mets ici mes notes pour la réalisation de scripts Bourne Shell dans un environnement GNU/Linux.

Les tableaux

Création

$ my_array=()

Ajouter un élément

$ element=banana
$ my_array+=($element)

Obtenir le nombre d'élément

$ echo "${#my_array[@]}"

Afficher le premier élément

$ echo "${my_array[0]}"

Afficher tous les éléments d'un tableau

x=0
while [ "$x" -lt "${#my_array[@]}" ]
do
	echo "${my_array[$x]}"
	x=$(( $x + 1 ))
done
for i in "${my_array[@]}"
do
	echo "$i"
done

Opérations Arithmétiques

Exemples

  • Addition 1 :
$ a=3
$ let a=a+1
$ echo $a
4
  • Addition 2 :
$ a=3
$ a=$((a+1))
$ echo $a
4

Case… Esac

Structure

case $1 in
	*.mp3)    echo "$1 is a mp3 file";;
	*.mkv)  echo "$1 is a mkv file";;
	*)
        echo "$1 is an unknown"
        echo "Format.";;
esac

Vérifier l'état de la dernière commande

if [ $? -eq 0 ] ; then

Les Opérateurs de Comparaison

  • Comparaisons :
    • String, Texte : =, !=, -n (non null), -z (null)
    • Numérique : -eq (égal), -ne (non égal), -lt (moins que), -gt (plus grand que), -ge (plus grand ou égal)
    • Logical operators : && (ET), || (OU), ! (NON)
    • File : -f (si existe), -d (si répertoire), -s (taille non null), -x (si le fichier est exécutable)

For… Do… Done

Structure

  • Exemple n°1 :
for x in 1 2 3
do
	echo $x
done
  • Exemple n°2 :
for s in www-0{1..8}
do
	echo $s
done

Gérer les espaces dans une boucle for

Par défaut si l'on stocke, le résultat d'une commande à l'intérieur d'une variable, et que l'on effectue une boucle for sur cette variable, alors les espaces, tabulations et nouvelles lignes seront considérés comme des nouvelles lignes.

Voyons cela dans un exemple inutile mais concret.

  • On place dans la variable text, un texte avec des espaces :
$ text="Body screaming fucking bloody mess"
  • Si nous effectuons une boucle loop nous pouvons voir que les espaces ont été remplacés par de nouvelles lignes :
for i in $text; do
	echo "$i"
done
Body
screaming
fucking
bloody
mess

C'est à cause de la valeur par défaut de l'IFS (Internal Field Separator) qui est : space, tab and newline.

Donc, pour éviter cela nous allons devoir le reparamétrer la variable IFS, pour indiquer que le champ de séparation ne doit être que pour les nouvelles lignes.

$ IFS=$'\n'
for i in $text; do
	echo "$i"
done
Body screaming fucking bloody mess

If… Then… Else… Fi

Structure

if [ -s $1 ]
then
	echo "$1 exist"
else
	echo "$1 doesn't exist"
fi

Exemples

Si la variable est nulle

if [ ! -n "$var" ]; then

Double condition if

  • Exemple n°1 :
if [ -n "$answer" ] && [ "$answer" != "N" ]; then
	echo "OK"
fi
  • Exemple n°2 :
if [ $(ssh user@192.168.1.200 mount | grep -q crypt_backup; echo $?) -eq "0" ] && [ $(ps -ef | grep -q [r]sync; echo $?) -ne "0" ] ; then
        echo "OK"
fi

Manipuler du texte

Substitution

  • % pour remplacer le suffixe. Ici on remplace l'extension du fichier :
$ FILE="The_Dolphins_-_Demo_-_Anemia.ogg"
$ echo "${FILE%.ogg}.mp3"
The_Dolphins_-_Demo_-_Anemia.mp3
  • # pour remplacer le préfixe :
$ FILE="The_Dolphins_-_Demo_-_Anemia.ogg"
$ echo "${FILE#The_Dolphins_-_Demo_-_}"
Anemia.ogg

Commande expr

Exemple n°1

$ line="secure-policy rule: 1"
$ expr match "$line" '.*: \([0-9]\+\)'
1

Exemple n°2

$ line="  name: STD01_to_ZYXEL_SSH"
$ expr match "$line" '.*: \([a-zA-Z0-9_]\+\).*'
STD01_to_ZYXEL_SSH

Lire un fichier ligne par ligne

while IFS= read -r line
do
	echo "$line"
done < /tmp/a_file.txt

Arréter un script sur erreurs

Source : https://wizardzines.com/

  • Arréter le script sur une erreur
$ set -e
  • Arréter le script si une variable n'est pas définit
$ set -u
  • Arréter le script si échec dans un pipe
$ set -o pipefail
  • Arréter le script sur une des erreurs définis ci dessus
$ set -euo pipefail

While… Do… Done

Structure

while [ $a -gt 0 ]
do
	echo "a=$a"
	let a=$a-1
done
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Contact :