Guide de base pour la création de scripts sous SHEL et Python

Publié le : 13/02/24
Modifié le : 24/06/24 à 17h17

Introduction au script Shell


Un script shell est un fichier texte, qui contient une suite de commandes shell qui sont exécuté par un interpréteur. Ces scripts permettent d'invoquer directement des commandes systèmes.
Les commandes shell retournent toujours :

  • Code de bon fonctionnement : 0/Aucune erreur; 1/ou autre une erreur;

Shell est un langage de commande et d'échange avec le système.
Quelques shell :

  • Bash pour Bourne Again Shell
  • csh, tcsh
  • ksh
Script de base
Shell
Python

Pour exécuter un script shell il faut lui donner les droits d'exécution :
chmod u+x nom_du_script.sh
u : Ajoute les droits d'exécution uniquement pour le propriétaire du fichier.

                                        
                                        #!/bin/bash
                                        echo "nous somme le " $(date)
                                        exit 0
                                        
                                        
                                        
                                        # -*- coding: utf-8 -*-
                                        #!/usr/bin/env python3
                                        # Importe le module datetime pour obtenir la date actuelle
                                        from datetime import datetime
                                            
                                        # Affiche un message avec la date actuelle
                                        print("Nous sommes le", datetime.now().strftime("%d/%m/%Y"))
                                            
                                        # Quitte le script avec succès
                                        exit(0)
                                        
                                        

Les variables en shell


Les variables en Shell, ne sont ni déclaré ni typé. On référence une variable avec le symbole $.
Les variables d'environnements sont mise à disposition pour nos scripts :

  • $USER : L'utilisateur actuellement connecté.
  • $PWD : Le répertoire courant.
  • $HOME : Le répertoire home de l'utilisateur connecté.
Exemple de script shell qui utilise les variales d'environnements
Shell
Python
                                        
                                        #!/bin/bash
                                        var_bjr1="bonjour les amis"
                                        var_bjr2=bonjour
                                        formatted_date=$(date +"%Y%m%d%H%M%S")

                                        echo $var_bjr1
                                        echo $var_bjr2
                                        echo $formatted_date

                                        echo L\'utilisateur connecté est : $USER
                                        echo Répertoire d\'exécution est : $PWD
                                        echo Répertoire de l\'utilisateur est : $HOME
                                        exit 0
                                        
                                        
                                        
                                        # -*- coding: utf-8 -*-
                                        #!/usr/bin/env python3
                                        import os
                                            
                                        # Déclarations de variables
                                        var_bjr1 = "bonjour les amis"
                                            
                                        # Affiche les variables et d'autres informations
                                        print(var_bjr1)
                                        print("L'utilisateur connecté est :", os.environ['USER'])
                                        print("Répertoire d'exécution est :", os.getcwd())
                                        print("Répertoire de l'utilisateur est :", os.path.expanduser('~'))
                                        
                                        
Variable Signification
$? Valeur de sortie de la dernière commande
$0 Nom du script
$n Nième argument passé au script
$# Nombre d'arguments reçus à partir de $1
$* Liste des arguments à partir de $1
$$ PID du processus courant
Shell
                                        
                                        #!/bin/bash
                                        echo "Ce script se nomme : " $0
                                        echo "Le premier argument passé est :" $1
                                        ./script_1.sh
                                        echo "La dernière commande a donné :" $? # 0 si aucune erreur
                                        exit 0
                                        
                                        
Concaténation
                            
                            #!/bin/bash
                            nom="ILLOURMANE"
                            prenom="Mahmoud"
                            nom_prenom="${nom}-${prenom}"
                            echo $nom_prenom

                            exit 0
                            
                            

Les conditionnelles


Les conditionnelles en shell scripting permettent d'exécuter des commandes ou des blocs de commandes basées sur des conditions spécifiques. Voici quelques exemples pour illustrer comment utiliser les conditionnelles en shell.

emoji_objects

-Comparaison de chaînes de caractères :
Pour les chaînes de caractères on doit utiliser : = ou == ou != ...
- Comparaison de numériques :
Pour comparer des numériques on doit utiliser les opérateurs : -eq, -lt, -gt ...

if fi
if elif else fi
case in

Tester si un fichier existe

                                        
                                        #!/bin/bash
                                        nombre1=5
                                        nombre2=10
                                        if [ $nombre1 -lt $nombre2 ]; then
                                            echo "$nombre1 est inférieur à $nombre2."
                                        else
                                            echo "$nombre1 n'est pas inférieur à $nombre2."
                                        fi
                                        
                                        

Tester plusieurs conditions avec -a (ET) et -o (OU)

                                        
                                        #!/bin/bash

                                        age=20
                                        ville="Paris"

                                        if [ $age -ge 18 ] -a [ "$ville" = "Paris" ]; then
                                            echo "Je suis majeur et je vis à Paris."
                                        elif [ $age -lt 18 ] -o [ "$ville" != "Paris" ]; then
                                            echo "Je suis mineur ou je ne vis pas à Paris."
                                        else
                                            echo "Autre situation."
                                        fi
                                        
                                        
Exécution
                                        
                                        mahmoud@Mahmoud:script_bash$ ./script_5.sh
                                            390
                                        
                                        
                                        
                                        #!/bin/bash
                                        choix="a"

                                        case $choix in
                                            a) echo "Option A sélectionnée.";;
                                            b) echo "Option B sélectionnée.";;
                                            *) echo "Option inconnue.";;
                                        esac
                                        
                                        

Les Boucles


for
while
untile
                                        
                                        #!/bin/bash

                                        for ville in "Paris" "Lyon" "Marseille"; do
                                            echo "Je visite $ville."
                                        done
                                        
                                        
                                        
                                        #!/bin/bash
                                        
                                        for i in 1 2 3 4 5; do
                                            echo "Nombre: $i"
                                        done
                                        
                                        
emoji_objects

L'utilisation de ; est nécessaire dans les deux exemples.

Dans cet exemple, je vérifie toutes les secondes si le fichier fichier.txt existe. Je limite l'attente à 10 secondes pour éviter une boucle infinie.

                                        
                                        #!/bin/bash

                                        compteur=0
                                        while [ ! -e fichier.txt ]; do
                                            echo "En attente de la création de fichier.txt..."
                                            sleep 1
                                            compteur=$((compteur+1))
                                            if [ $compteur -eq 10 ]; then
                                                echo "Temps d'attente dépassé."
                                                break
                                            fi
                                        done
                                        
                                        

Réessayer une opération jusqu'à sa réussite.

                                        
                                        #!/bin/bash

                                        compteur=0
                                        until [ -e fichier.txt ]; do
                                            echo "Tentative $compteur: fichier.txt non trouvé."
                                            sleep 1
                                            compteur=$((compteur+1))
                                            touch fichier_script_untile.txt # Pour cet exemple, je crée le fichier après quelques tentatives.
                                            if [ $compteur -eq 5 ]; then
                                                echo "Fichier créé pour terminer la boucle."
                                                break
                                            fi
                                        done
                                        
                                        

Opérations sur les variables


Opérations mathématiques
Incrémentation
Addition 1
Addition 2
                                        
                                        #!/bin/bash
                                        var1=0
                                        echo $var1
                                        let var1++
                                        echo $var1
                                        
                                        
Exécution
                                        
                                        mahmoud@Mahmoud:script_bash$ ./script_4.sh
                                            0
                                            1
                                        
                                        
                                        
                                        #!/bin/bash
                                        var2=45
                                        var3=$(($var2+345))
                                        echo $var3
                                        
                                        
Exécution
                                        
                                        mahmoud@Mahmoud:script_bash$ ./script_5.sh
                                            390
                                        
                                        
                                        
                                        #!/bin/bash
                                        var4=45
                                        var5=$[$var2+347]
                                        echo $var5
                                        
                                        
Exécution
                                        
                                        mahmoud@Mahmoud:script_bash$ ./script_5.sh
                                            347
                                        
                                        
emoji_objects

Il faut faire attention au espaces var5=45 et non var5 = 45

Opérations sur les tableaux


On Shell, les tableaux sont assez flexibles ils peuvent être considéré comme des listes, des tableaux..
On peut ajouter des élements à la volé.

Shell
Déclaration global
                                        
                                        #!/bin/bash
                                        tab=("Mahmoud" "ILLOURMANE")
                                        exit 0
                                        
                                        
Déclaration individuelle
                                        
                                        #!/bin/bash
                                        tab1[0] = "Mahmoud"
                                        tab1[1] = "ILLOURMANE"
                                        exit 0
                                        
                                        
Les tableau associatif

les tableaux associatifs existent dans le shell Bash à partir de la version 4.0

                                        
                                        #!/bin/bash

                                        # Déclare un tableau associatif
                                        declare -A tab_vms
                                        
                                        # Remplir le tableau associatif
                                        tab_vms["VM1"]="05d4ddb6-090a-8992-a71f-6ea54ee89fef"
                                        tab_vms["VM2"]="55042bd4-9ee0-d1a2-d9ea-55c2eef69683"
                                        
                                        # Parcours du tableau associatif
                                        for vm_name in "${!tab_vms[@]}"; do
                                            # Obtenir l'UUID de la VM en fonction du nom
                                            vm_uuid=${tab_vms[$vm_name]}
                                        
                                            echo "Traitement de la VM : $vm_name avec l'UUID : $vm_uuid"
                                        done
                                        
                                        exit 0
                                        
                                        
Affichage
                                        
                                        #!/bin/bash
                                        echo ${tab[0]}
                                        
                                        # Affichage de tout le tableau
                                        echo ${tab[@]}
                                        exit 0
                                        
                                        
Obtenir la taille d'un tableau
                                        
                                        #!/bin/bash
                                        tab=("Mahmoud" "ILLOURMANE" 25)
                                        echo ${#tab[*]}

                                        # Stockage de la taille dans une variable
                                        len=${#tab[*]}
                                        echo $len
                                        exit 0
                                        
                                        
Parcourir un tableau
                                        
                                        #!/bin/bash

                                        # Définition du tableau
                                        tab=("Mahmoud" "ILLOURMANE")
                                            
                                        for element in "${tab[@]}"; do
                                            echo "Traitement de l'élément : $element"
                                        done
                                        exit 0
                                        
                                        
emoji_objects

- Il ne doit pas y avoir d'espace entre le nom du tableau tab=(
- Il doit y avoir uniquement un espace entre les éléments du tableau.
- Bash ne fera aucune vérification sur les éléments donc si on essaye d'appeler une case qui n'existe pas on aura aucun avertissement.

Tests


Les tests en shell, souvent réalisés avec la commande test ou les crochets [ ], sont utilisés pour évaluer des expressions conditionnelles dans les scripts Shell. Voici un résumé des points clés :

  • Test de Conditions : Les tests permettent de vérifier différentes conditions telles que l'existence d'un fichier, la comparaison de chaînes de caractères ou de nombres, etc.
  • Commande test : La commande test est utilisée pour effectuer des tests conditionnels. Elle prend en entrée une expression conditionnelle et renvoie 0 (vrai) si la condition est vraie et 1 (faux) sinon.
  • Crochets [ ] : Les crochets [ ] sont une alternative à la commande test. Ils fonctionnent de la même manière mais nécessitent un espace avant et après les crochets. Ils sont souvent utilisés pour améliorer la lisibilité du code.
Opérateurs de Comparaison :

Les tests permettent d'utiliser différents opérateurs de comparaison tels que :

  • -eq : égal =
  • -ne : différent !=
  • -lt : inférieur <
  • -gt : supérieur >
  • -le : inférieur ou égal <=
  • -ge : supérieur ou égal >=
Tests sur les fichiers
  • -e : Le fichier existe
  • -f : C'est un fichier
  • -d : C'est un répertoire
  • -r | -w | -x : Propriété du fichier
  • -s : Non vide
  • f1 -nt f2 : Plus récent que
  • f1 -ot f2 : Plus vieux que
Exemples
-e
-f
-d
-(r,w,x)
-s
-nt
-ot

Ce script vérifie que un nom de fichier qu'on passe en paramètre est bien présent dans le répertoire courant où se trouve le script.

                                        
                                        #!/bin/bash

                                        # Affiche l'usage du script si aucun argument n'est fourni
                                        if [ $# -eq 0 ]; then
                                            echo "Usage: $0 "
                                            exit 1
                                        fi
                                            
                                        # Définit le nom du fichier à partir du premier argument
                                        file="$1"
                                            
                                        # Tente d'obtenir le chemin absolu du répertoire contenant le script
                                        # et vérifie si l'opération réussit
                                        script_dir=$(dirname "$(readlink -f "$0")") || { echo "Erreur lors de la résolution du chemin du script"; exit 1; }
                                            
                                        # Construit le chemin complet vers le fichier ciblé
                                        file_path="${script_dir}/${file}"
                                            
                                        # Vérifie l'existence du fichier et affiche un message approprié
                                        if [ -e "$file_path" ]; then
                                            echo "Le fichier ${file} existe dans le même répertoire que le script."
                                        else
                                            echo "Le fichier ${file} n'existe pas dans le même répertoire que le script."
                                        fi
                                        
                                        

Exécution

                                        
                                        mahmoud@Mahmoud:script_bash$ ./script_6_file_exist.sh
                                            Usage: ./script_6_file_exist.sh <nom_du_fichier> 
                                        mahmoud@Mahmoud:script_bash$ ./script_6_file_exist.sh script_1.sh
                                            Le fichier script_1.sh existe dans le même répertoire que le script.
                                        mahmoud@Mahmoud:script_bash$ ./script_6_file_exist.sh script_5.sh
                                            Le fichier script_5.sh n'existe pas dans le même répertoire que le script.
                                        
                                        

Ce script vérifie que le paramètre transmi est bien un fichier.

                                        
                                        #!/bin/bash

                                        # Vérifie si au moins un argument est fourni
                                        if [ $# -eq 0 ]; then
                                            echo "Je dois utiliser ce script comme suit: $0 <nom_du_fichier>"
                                            exit 1
                                        fi
                                            
                                        # Assigne le nom du fichier fourni à une variable
                                        fichier="$1"
                                            
                                        # Vérifie si le fichier existe et est un fichier
                                        if [ -f "$fichier" ]; then
                                            echo "Le fichier '$fichier' existe et c'est un fichier."
                                        else
                                            if [ -e "$fichier" ]; then
                                                echo "Le fichier '$fichier' existe mais ce n'est pas un fichier."
                                            else
                                                echo "Le fichier '$fichier' n'existe pas."
                                            fi
                                        fi                    
                                        
                                        

Exécution

                                        
                                        mahmoud@Mahmoud:script_bash$ ./script_7_est_un\ _fic.sh script_
                                            Le fichier 'script_' n'existe pas.
                                        mahmoud@Mahmoud:script_bash$ ./script_7_est_un\ _fic.sh script_1.sh
                                            Le fichier 'script_1.sh' existe et c'est un fichier régulier.
                                        mahmoud@Mahmoud:script_bash$ mkdir test/
                                        mahmoud@Mahmoud:script_bash$ ./script_7_est_un\ _fic.sh test/
                                            Le fichier 'test/' existe mais ce n'est pas un fichier régulier.
                                        mahmoud@Mahmoud:script_bash$
                                        
                                        

Ce script vérifie que le paramètre transmi est bien un repertoire.

                                        
                                        #!/bin/bash

                                        # Vérifie si un argument est fourni
                                        if [ $# -eq 0 ]; then
                                            echo "Je dois utiliser ce script comme suit: $0 <nom_du_répertoire>"
                                            exit 1
                                        fi
                                        
                                        # Assigne le nom du répertoire fourni à une variable
                                        repertoire="$1"
                                            
                                        # Vérifie si le chemin existe et est un répertoire
                                        if [ -d "$repertoire" ]; then
                                            echo "Le répertoire '$repertoire' existe."
                                        else
                                            echo "Le répertoire '$repertoire' n'existe pas ou ce n'est pas un répertoire."
                                        fi                  
                                        
                                        
Exécution
                                        
                                        mahmoud@Mahmoud:script_bash$ ./script_8_est_un_repertoire.sh
                                            Je dois utiliser ce script comme suit: ./script_8_est_un_repertoire.sh <nom_du_répertoire>
                                        mahmoud@Mahmoud:script_bash$ ./script_8_est_un_repertoire.sh test
                                            Le répertoire 'test' existe.
                                        mahmoud@Mahmoud:script_bash$ ./script_8_est_un_repertoire.sh testd
                                            Le répertoire 'testd' n'existe pas ou ce n'est pas un répertoire.
                                        
                                        

Ce script vérifiera et affichera les permissions dont dispose l'utilisateur pour ce fichier.

                                        
                                        #!/bin/bash

                                        # Vérifie si un argument est fourni
                                        if [ $# -eq 0 ]; then
                                            echo "Je dois utiliser ce script comme suit: $0 <nom_du_fichier>"
                                            exit 1
                                        fi
                                            
                                        # Assigne le nom du fichier fourni à une variable
                                        fichier="$1"
                                            
                                        # Vérifie si le fichier est lisible
                                        if [ -r "$fichier" ]; then
                                            echo "Je peux lire le fichier '$fichier'."
                                        else
                                            echo "Je ne peux pas lire le fichier '$fichier'."
                                        fi
                                            
                                        # Vérifie si le fichier est modifiable
                                        if [ -w "$fichier" ]; then
                                            echo "Je peux modifier le fichier '$fichier'."
                                        else
                                            echo "Je ne peux pas modifier le fichier '$fichier'."
                                        fi
                                        
                                        # Vérifie si le fichier est exécutable
                                        if [ -x "$fichier" ]; then
                                            echo "Je peux exécuter le fichier '$fichier'."
                                        else
                                            echo "Je ne peux pas exécuter le fichier '$fichier'."
                                        fi                                         
                                        
                                        
Exécution
                                        
                                        mahmoud@Mahmoud:script_bash$ ls -l script_1.sh
                                            -rwxrwxrwx 1 mahmoud mahmoud 48 Feb 13 10:11 script_1.sh
                                        mahmoud@Mahmoud:script_bash$ ./script_9_perm_fic.sh script_1.sh
                                            Je peux lire le fichier 'script_1.sh'.
                                            Je peux modifier le fichier 'script_1.sh'.
                                            Je peux exécuter le fichier 'script_1.sh'.
                                        
                                        

Ce script prend en paramètre un nom de fichier et vérifie si ce fichier existe et a une taille supérieure à zéro, en utilisant l'opérateur -s.

                                        
                                        #!/bin/bash

                                        # Vérifie si un argument est fourni
                                        if [ $# -eq 0 ]; then
                                            echo "Je dois utiliser ce script comme suit: $0 <nom_du_fichier>"
                                            exit 1
                                        fi
                                            
                                        # Assigne le nom du fichier fourni à une variable
                                        fichier="$1"
                                            
                                        # Vérifie si le fichier existe et a une taille supérieure à zéro
                                        if [ -s "$fichier" ]; then
                                            echo "Le fichier '$fichier' existe et n'est pas vide."
                                        else
                                            # Vérifie si le fichier existe, même s'il est vide
                                            if [ -e "$fichier" ]; then
                                                echo "Le fichier '$fichier' existe mais est vide."
                                            else
                                                echo "Le fichier '$fichier' n'existe pas."
                                            fi
                                        fi                                                
                                        
                                        
Exécution
                                        
                                        mahmoud@Mahmoud:script_bash$ touch test2.txt
                                        mahmoud@Mahmoud:script_bash$ ./script_10_fic_non_vide.sh test2.txt
                                            Le fichier 'test2.txt' existe mais est vide.
                                        mahmoud@Mahmoud:script_bash$ ./script_10_fic_non_vide.sh script_1.sh
                                            Le fichier 'script_1.sh' existe et n'est pas vide.
                                        
                                        

Ce script qui prend en paramètre deux noms de fichiers et vérifie si le premier fichier est plus récent que le second en utilisant l'opérateur -nt.

                                        
                                        #!/bin/bash

                                        # Vérifie si deux arguments sont fournis
                                        if [ $# -ne 2 ]; then
                                            echo "Je dois utiliser ce script comme suit: $0 <fichier1> <fichier2>"
                                            exit 1
                                        fi
                                            
                                        # Assigne les noms des fichiers fournis à des variables
                                        fichier1="$1"
                                        fichier2="$2"
                                            
                                        # Vérifie si fichier1 est plus récent que fichier2
                                        if [ "$fichier1" -nt "$fichier2" ]; then
                                            echo "Le fichier '$fichier1' est plus récent que le fichier '$fichier2'."
                                        elif [ "$fichier2" -nt "$fichier1" ]; then
                                            echo "Le fichier '$fichier2' est plus récent que le fichier '$fichier1'."
                                        else
                                            echo "Les fichiers '$fichier1' et '$fichier2' ont la même date de modification ou l'un d'eux n'existe pas."
                                        fi                                                           
                                        
                                        
Exécution
                                        
                                        mahmoud@Mahmoud:script_bash$ ./script_11_nt.sh script_1.sh script_2.sh
                                            Le fichier 'script_2.sh' est plus récent que le fichier 'script_1.sh'.
                                        
                                        

Ce script qui prend en paramètre deux noms de fichiers et vérifie si le premier fichier est plus ancien que le second en utilisant l'opérateur -ot.

                                        
                                        #!/bin/bash

                                        # Vérifie si deux arguments sont fournis
                                        if [ $# -ne 2 ]; then
                                            echo "Je dois utiliser ce script comme suit: $0 <fichier1> <fichier2>"
                                            exit 1
                                        fi
                                            
                                        # Assigne les noms de fichiers fournis aux variables
                                        fichier1="$1"
                                        fichier2="$2"
                                            
                                        # Vérifie si fichier1 est plus ancien que fichier2
                                        if [ "$fichier1" -ot "$fichier2" ]; then
                                            echo "Le fichier '$fichier1' est plus ancien que '$fichier2'."
                                        elif [ "$fichier2" -ot "$fichier1" ]; then
                                            echo "Le fichier '$fichier2' est plus ancien que '$fichier1'."
                                        else
                                            echo "Les fichiers '$fichier1' et '$fichier2' ont la même date de modification ou l'un d'eux n'existe pas."
                                        fi                                                          
                                        
                                        
Exécution
                                        
                                        mahmoud@Mahmoud:script_bash$ ./script_12_ot.sh script_1.sh script_2.sh
                                            Le fichier 'script_1.sh' est plus ancien que 'script_2.sh'.
                                        
                                        
Expressions Logiques
  • exp1 -a exp2 : ET
  • exp1 -o exp2 : OU
  • !exp : Négation
Exemples
-a
-o
!

Ce script vérifie si deux chaînes fournies sont non vides.

                                        
                                        #!/bin/bash

                                        # Vérifie si les deux chaînes sont non vides
                                        if [ -n "$1" -a -n "$2" ]; then
                                            echo "Les deux chaînes sont non vides."
                                        else
                                            echo "Au moins une des deux chaînes est vide."
                                        fi
                                        
                                        

Ce script vérifie si au moins une des deux chaînes fournies est non vide.

                                        
                                        #!/bin/bash

                                        # Vérifie si au moins une des deux chaînes est non vide
                                        if [ -n "$1" -o -n "$2" ]; then
                                            echo "Au moins une des deux chaînes est non vide."
                                        else
                                            echo "Les deux chaînes sont vides."
                                        fi 
                                        
                                        

Ce script vérifie si une chaîne est vide.

                                        
                                        #!/bin/bash

                                        # Vérifie si la chaîne est vide en utilisant la négation
                                        if [ ! -n "$1" ]; then
                                            echo "La chaîne est vide."
                                        else
                                            echo "La chaîne n'est pas vide."
                                        fi                    
                                        
                                        
Tests sur les chaînes de caractères
  • -z Chaîne vide
  • -n Chaîne non vide
  • != Différentes
  • = Identiques
Exemples
-z
-n
!=
=

Ce script vérifie si la chaîne de caractères fournie est vide.

                                        
                                        #!/bin/bash

                                        # Vérifie si la chaîne de caractères est vide
                                        if [ -z "$1" ]; then
                                            echo "La chaîne est vide."
                                        else
                                            echo "La chaîne n'est pas vide."
                                        fi
                                        
                                        

Ce script vérifie si la chaîne de caractères fournie est non vide.

                                        
                                        #!/bin/bash

                                        # Vérifie si la chaîne de caractères est non vide
                                        if [ -n "$1" ]; then
                                            echo "La chaîne n'est pas vide."
                                        else
                                            echo "La chaîne est vide."
                                        fi    
                                        
                                        

Ce script compare deux chaînes de caractères et vérifie si elles sont différentes.

                                        
                                        #!/bin/bash

                                        # Vérifie si les chaînes de caractères sont différentes
                                        if [ "$1" != "$2" ]; then
                                            echo "Les chaînes sont différentes."
                                        else
                                            echo "Les chaînes sont identiques."
                                        fi                    
                                        
                                        

Ce script compare deux chaînes de caractères et vérifie si elles sont identiques.

                                        
                                        #!/bin/bash

                                        # Vérifie si les chaînes de caractères sont identiques
                                        if [ "$1" = "$2" ]; then
                                            echo "Les chaînes sont identiques."
                                        else
                                            echo "Les chaînes sont différentes."
                                        fi
                                        
                                        

La Gestion des Flux


emoji_objects

- Entrée standard (stdin) : C'est le flux par lequel le processus reçoit des données. Son descripteur de fichier est 0.
- Sortie standard (stdout) : C'est le flux par lequel le processus envoie des données vers l'écran par défaut, par exemple le terminal. Son descripteur de fichier est 1.
- Sortie d'erreur standard (stderr) : C'est le flux utilisé par le processus pour envoyer des messages d'erreur. Son descripteur de fichier est 2.
Exemples d'utilisation dans la section : Redirection du flux d'erreur

Redirection d'entrée standard depuis un fichier

Lire le contenu d'un fichier et l'utiliser comme entrée pour une commande.
Dans cet exemple, je redirige le contenu du fichier noms.txt vers la commande sort, qui va trier les lignes du fichier.

                            
                            #!/bin/bash
                            file="$1"
                            sort < "$file"
                            
                            
Redirection du flux standard

Écrire la sortie d'une commande dans un fichier.

                            
                            #!/bin/bash
                            echo "Bonjour le monde" > sortie.txt
                            
                            
Redirection du flux d'erreur

Dans cet exemple, je cherche le mot "recherche" dans un fichier qui n'existe pas, et je redirige les erreurs générées dans le fichier erreurs.txt.

                            
                            #!/bin/bash
                            grep "recherche" fichier_inexistant.txt 2> erreurs.txt
                            
                            
Redirection de la sortie d'erreur vers la sortie standard

Rediriger à la fois la sortie standard et la sortie d'erreur vers le même fichier.

                            
                            #!/bin/bash
                            commande 2>&1 > sortie_et_erreurs.txt
                            
                            
emoji_objects

Ici, je redirige la sortie d'erreur (2>) sur la sortie standard (&1), puis je redirige cette dernière dans un fichier
(> sortie_et_erreurs.txt).

Redirection dans un fichier (écriture et création du fichier)

Créer un fichier ou écraser le contenu s'il existe déjà, avec la sortie d'une commande.

                            
                            #!/bin/bash
                            echo "Je crée ou j'écrase un fichier" > nouveau_fichier.txt
                            
                            
Ajout à un fichier

Ajouter la sortie d'une commande à la fin d'un fichier existant.

                            
                            #!/bin/bash
                            echo "J'ajoute cette ligne à la fin du fichier" >> fichier_existant.txt
                            
                            
Ecriture dans un fichier

Dans cet exemple, je commence par récupérer la date et l'heure actuelles avec la commande date que je stocke dans la variable date_now. Ensuite, je crée un fichier date_info.txt où je vais écrire la date et l'heure. Avec l'opérateur > je crée le fichier ou j'écrase son contenu s'il existe déjà. Avec l'opérateur >>, je vais ajouter la liste des fichiers et dossiers du répertoire courant à la suite dans le fichier sans écraser le contenu précédent.

                            
                            #!/bin/bash

                            # Je stocke la commande `date` dans la variable date_now
                            date_now=$(date)
                                
                            # Je crée un fichier nommé 'date_info.txt'
                            # Je vais écrire la date et l'heure actuelles dedans
                            echo "La date et l'heure actuelles sont : $date_now" > date_info.txt
                                
                            # Ensuite, je vais lister le contenu du répertoire courant et ajouter cette liste au même fichier
                            echo "Liste des fichiers et dossiers:" >> date_info.txt
                            ls >> date_info.txt        
                            
                            
                            
                            #!/bin/bash

                            list=$(ls)
                            for element in $list
                            do
                                echo $element >> ./toto.txt
                            done   
                            
                            

                            
                            #!/bin/bash

                            list=$(cat toto.txt)
                            for element in $list
                            do
                                echo $element >> ./nouveau_toto.txt
                            done
                            
                            
Lecture d'un fichier

Dans cette exemple, je vais lire le contenu d'un fichier ligne par ligne et afficher chaque ligne avec un numéro précédant le texte.

                            
                            #!/bin/bash

                            filename='date_info.txt'
                            i=1
                            while read line; do
                                # Affichage du numéro de ligne et du contenu de la ligne
                                echo "Ligne $i: $line"
                                i=$((i + 1))
                            done < $filename    
                            
                            

                            
                            #!/bin/bash

                            cpt=1
                            while read LINE
                            do
                                echo $cpt ": " $LINE
                                let cpt++
                            done < toto.txt
                            
                            

Lecture de l'entrée clavier


                            
                            #!/bin/bash

                            echo "Entrez votre nom, prénom et âge :"
                            read nom prenom age
                            echo "Je m'appelle $prenom $nom et j'ai $age ans."
                            
                            
Exécution
                            
                                mahmoud@Mahmoud:script_bash$ ./script_19_read.sh
                                    Entrez votre nom, prénom et âge :
                                    illourmane mahmoud 25
                                    Je m'appelle mahmoud illourmane et j'ai 25 ans.
                            
                            
Configuration d'un conteneur Docker
                            
                                #!/bin/bash

                                echo "Entrez le nom de l'image, le tag et le nom du conteneur :"
                                read image tag nom_conteneur
                                echo "Je lance un conteneur Docker avec l'image $image:$tag appelé $nom_conteneur."
                                docker run --name $nom_conteneur $image:$tag
                            
                            
Exécution
                            
                                mahmoud@Mahmoud:script_bash$ ./script_20_docker.sh
                                    Entrez le nom de l'image, le tag et le nom du conteneur :
                                    nginx lastest mon-nginx
                                    Je lance un conteneur Docker avec l'image nginx:lastest appelé mon-nginx.
                            
                            

Les fonctions


En shell script, il n'est pas requis de spécifier explicitement les paramètres lors de la déclaration d'une fonction. Les fonctions ont la capacité d'accéder aux variables globales ou d'utiliser les arguments passés directement via des paramètres positionnels.
De plus, l'appel d'une fonction se fait sans parenthèses, se distinguant ainsi des syntaxes des langages de programmation tels que Python ou Java. On appelle simplement la fonction par son nom suivi de ses arguments.

Fonction sans paramètre
                            
                            #!/bin/bash

                            # Déclaration de la fonction
                            fun_1() {
                                echo L\'utilisateur qui lance la fonction est : $USER
                            }

                            # Appel de la fonction
                            fun_1
                            
                            
Fonction avec paramètres

Dans cet exemple, la fonction attend deux paramètres envoyés en argument pour additionner deux chiffres.

                            
                            #!/bin/bash

                            fun_2() {
                                let result=$1+$2
                                result2=$(($1 + $2))
                                echo 1-Le résultat de l\'addition est : $result
                                echo 2-Le résultat de l\'addition est : $result2
                            }

                            fun_2 $1 $2
                            
                            
Fonction avec paramètre entré au clavier
                            
                            #!/bin/bash

                            fun_3() {
                                echo "En Fahrenheit, cela fait : $((($1 * 9/5) + 32))°F"
                            }
                                
                            echo "Entrez la température en Celsius :"
                            read celsius
                                
                            fun_3 $celsius
                            
                            
Une fonction qui vérifie si un fichier existe
                            
                            #!/bin/bash

                            fun_4() {
                                if [[ -e $1 ]]; then
                                    echo "Le fichier $1 existe."
                                else
                                    echo "Le fichier $1 n'existe pas."
                                fi
                            }
                                
                            echo "Entrez le nom du fichier à vérifier :"
                            read nomFichier
                                
                            fun_4 $nomFichier
                            
                            

Manipuler des chaînes de caractères


En shell il est possible de manipuler les chaînes de caractères pour extraires des informations, modifier un symbol délimiteur etc.
Cela simplifier les programmes, et évite l'utilisation d'expression régulière.
Attention dans le cas des séparateurs, les modifications sont persistantes.

Extraction d'une chaîne/partie d'une Chaîne

la syntaxe ${c:p:n} permet d'extraire une chaîne ou une partie d'une chaîne facilement.

emoji_objects

${ chaine : position : nombre_de_caractères }
- Il n'y a pas d'espace entre les : et {}.
- chaine : La chaîne dont on souhaite extraire les informations.
- position : La position (à partir de 0) à laquelle on souhaite débuter.
- nombre_de_caractères : Le nombre de caractères qu'on souhaite extraire.
- Cela ignore les espaces mais ils sont comptabilisé.

                                
                                #!/bin/bash

                                chaine="Bonjour à tous"
                                chaine2=${chaine:7:3}
                                chaine3=${chaine:10:4}
                                echo $chaine
                                echo $chaine2
                                echo $chaine3
                                
                                
Exécution
                                
                                mahmoud@Mahmoud:script_bash$ ./script_1_chaine_extrac.sh
                                    Bonjour à tous
                                    à
                                    tous
                                
                                

Trancature d'une chaîne de caractères

la syntaxe ${ c : n } permet de tranquer une chaîne de caractères.

                                
                                #!/bin/bash

                                chaine="Bonjour à tous"
                                chaine2=${chaine:10}
                                echo $chaine
                                echo $chaine2
                                
                                
Exécution
                                
                                mahmoud@Mahmoud:script_bash$  ./script_2_trancature.sh
                                    Bonjour à tous
                                    tous
                                
                                

Séparateur IFS


En programmation shell, la variable IFS, pour 'Internal Field Separator', est fondamentale pour lire et interpréter correctement les données. Elle définit le séparateur de champ à utiliser lors de la division d'une ligne de texte en mots.
Par défaut, elle inclut le retour à la ligne (newline), l'espace (space) et la tabulation (tab), mais je peux la redéfinir pour changer le comportement de split implicite selon mes besoins spécifiques.

emoji_objects

- Modification persistante

Redéfinition de l'IFS espace

                                
                                #!/bin/bash

                                oldIFS=$IFS
                                chaine="Bonjour;Hello;Hola"
                                echo $chaine
                                # Redéfinition de l'IFS
                                IFS=';'
                                echo $chaine
                                # Remise à la normale
                                IFS=$oldIFS
                                echo $chaine
                                
                                
Exécution
                                
                                mahmoud@Mahmoud:script_bash$  ./script_1_ifs.sh
                                    Bonjour;Hello;Hola
                                    Bonjour Hello Hola
                                    Bonjour;Hello;Hola
                                
                                

Redéfinition de l'IFS pour un fichier

                                
                                #!/bin/bash

                                # Définition de la fonction d'affichage
                                afficher_infos() {
                                    local IFS_SAVE=$IFS  # Sauvegarde de l'IFS actuel
                                    IFS=';'              # Définition de la virgule comme nouveau IFS
                                    for var in $1 
                                    do
                                        echo $var
                                    done
                                    IFS=$IFS_SAVE
                                    echo "======="
                                }
                                    
                                # Lecture du fichier ligne par ligne
                                while read LINE 
                                do
                                    afficher_infos $LINE
                                done < "fic.txt"
                                
                                
Exécution
                                
                                # Fichier fic.txt
                                Hello;Bonjour;Hola
                                Azerty;Qwerty
                                Python;Shell

                                mahmoud@Mahmoud:script_bash$   ./script_2_ifs.sh
                                    Hello
                                    Bonjour
                                    Hola
                                    =======
                                    Azerty
                                    Qwerty
                                    =======
                                    Python
                                    Schell
                                    =======
                                
                                

Appel système


Exécution d'un appel système pour installer un package :

                            
                            #!/bin/bash

                            # Exécute la commande apt install
                            apt install <package_name>
                                
                            # Vérifie le code de retour de la commande
                            if [ $? -ne 0 ]; then
                                # En cas d'erreur, affiche un message d'erreur et quitte avec un code de sortie non nul
                                echo "Erreur lors de l'installation du paquet."
                                exit 1
                            else
                                # Si la commande s'est exécutée avec succès, affiche un message de réussite
                                echo "Installation du paquet terminée avec succès."
                            fi
                            
                            
content_copy

Pour gérer les erreurs on peux utiliser un mélange de redirections de sortie et de structures de contrôle pour afficher les messages d'erreur :

                            
                            #!/bin/bash

                            # Fonction pour afficher les messages d'erreur
                            print_error() {
                                echo "Erreur: $1" >&2
                            }
                                
                            # Exécute la commande apt install
                            if ! output=$(apt install  2>&1); then
                                print_error "Impossible d'installer le paquet."
                                print_error "$output"
                                exit 1
                            fi
                                
                            # Si la commande s'est exécutée avec succès, affiche un message de réussite
                            echo "Installation du paquet terminée avec succès."        
                            
                            
content_copy
Extraire une information

Dans cet exemple, nous allons voir comment extraire une information contenu dans une sortie d'appel système :

                            
                            xe snapshot-list params=uuid
                                uuid ( RO)    : b4568bdb-0aad-f63f-5a15-610421a65614
                                uuid ( RO)    : e729e7a2-391f-6312-7d28-5ea5006615a7
                            
                            

Le but ici est d'extraire uniquement la valeur de l'uuid. Pour cela nous allons utiliser awk, cette commande permet d'extraire des champs spécifiques à partir de la sortie de commande en spécifiant le délimiteur (par défaut, c'est l'espace ou la tabulation) et le numéro de champ.
En partant de la sortie précédente, on voit que chaque ligne contient un préfixe uuid ( RO) : suivi de l'UUID.
Dans ce cas, le préfixe uuid ( RO) : compte comme quatre champs lorsqu'on considère l'espace comme délimiteur :
- Champ 1 : uuid
- Champ 2 : (
- Champ 3 : RO)
- Champ 4 : ":"
L'UUID lui-même commence après ces quatre champs et est donc considéré comme le cinquième champ.
En utilisant awk, on utilisant on peut spécifier quel champ on souhaite extraire :

                            
                            xe snapshot-list params=uuid | awk '/uuid \( RO\)/ {print $5}'
                            
                            
emoji_objects

Nous n'avons pas spécifié les caractères ":" car :
L'utilisation de /uuid \( RO\)/ emploie une expression régulière pour rechercher les lignes qui contiennent uuid ( RO) :.
Entre uuid et (, il y a un espace, et de même entre ( et RO). Cependant, entre RO) et :, il y a plus d'espace. Nous pouvons donc nous contenter de chercher le motif sans les :, et cela fonctionnera.

Commandes avec interactions

Lorsqu'une commande attend une réponse yes ou autre chose de notre part, nous pouvons l'automatiser en utilisant un pipe | avec les commandes echo ou yes. Cela nous permet de gérer les confirmations requises dans un script. Voici comment scripter ce genre d'appel :

Méthode 1 : Utiliser echo avec un pipe (|)

On utilise echo pour envoyer une réponse (yes ou no) à une commande qui attend une confirmation.
Exemple : Pour une commande qui attend yes pour continuer, on peut utiliser echo avec un pipe (|) :

                            
                            #!/bin/bash
                        
                            echo "yes" | xe template-uninstall template-uuid=$tmp_uuid_template 

                            exit 0
                            
                            
content_copy
Méthode 2 : Utiliser yes

La commande yes répète en continu une réponse (yes ou no) et la pipe à la commande.
Exemple : Pour envoyer en continu yes à une commande :

                            
                            #!/bin/bash
                        
                            yes | xe template-uninstall template-uuid=$tmp_uuid_template 

                            exit 0
                            
                            
content_copy

Nous pouvons personnaliser la réponse répétée par yes en ajoutant l'argument souhaité :

                            
                            #!/bin/bash
                        
                            yes "yes" | xe template-uninstall template-uuid=$tmp_uuid_template 

                            exit 0
                            
                            
content_copy
emoji_objects

Pour certaines commandes, l'approche consistant à utiliser (yes) peut ne pas fonctionner.

Introduction aux scripts Python


En Python, l'écriture est simplifiée tout en exploitant judicieusement les modules, en gardant à l'esprit que Python est un langage interprété.
Il est important de faire attention aux différences entre Python 2.x et 3.x, notamment en termes d'évolution de la bibliothèque standard et du codage en UTF-8, et de comprendre que dans ce langage, tout est traité comme un objet, y compris les fonctions comme `print`.

Scripting Système en Python

Python pour le scripting système permet l'exploitation des éléments système, offre un codage spécifique pour la gestion de ces éléments, et utilise des bibliothèques telles que sys pour interagir avec l'interpréteur, os pour accéder aux fonctionnalités du système d'exploitation et subprocess pour exécuter des processus externes.

                            
                            #!/usr/bin/env python3
                            import sys
                                
                            print(f"Nombre d'arguments {len(sys.argv)}")
                            print(sys.argv[0])
                            exit(0)
                            
                            
emoji_objects

- #!/usr/bin/env python3 : Cette ligne est un shebang, qui indique au système d'exploitation quel interpréteur utiliser pour exécuter le script.
- import sys : Cette ligne importe le module sys, qui fournit un accès à certaines variables utilisées ou maintenues par l'interpréteur Python, ainsi qu'à des fonctionnalités spécifiques au système.
- exit(0) : Fin de script 0 : OK, X : ERREUR.

Exécution
                            
                            mahmoud@Mahmoud:/script_python$ python3 s_1.py
                                Nombre d'arguments 1
                                s_1.py
                            
                            mahmoud@Mahmoud:/script_python$ python3 s_1.py test
                                Nombre d'arguments 2
                                s_1.py
                            
                            

Obtenir des informations sur la plateforme d'exécution du script.

                            
                            #!/usr/bin/env python3
                            import sys, os
                                
                            print(f"Plate-forme d'exécution :  {sys.platform}, {os.name}")
                            exit(0)
                            
                            
Exécution
                            
                            mahmoud@Mahmoud:/script_python$ python3 s_2 .py
                                Plate-forme d'exécution :  linux, posix
                            
                            

Les Flux Standards

Les flux standards (stdin, stdout, stderr) sont définis dans le package sys.
Les opérations d'entrées/sorties sont définis avec read(sur stdin)/write.

  Ecritures sur les flux stdout, stderr

                            
                            #!/usr/bin/env python3
                            import sys

                            sys.stdout.write("J'écris sur la sortie standard \n")
                            sys.stderr.write("J'écris sur la sortie d'erreur \n")
                            exit(0)
                            
                            
Exécution
                            
                            mahmoud@Mahmoud:/script_python$ python3 s_3 .py
                                J'écris sur la sortie standard
                                J'écris sur la sortie d'erreur
                            
                            

  Lecture sur le flux stdin

                            
                            #!/usr/bin/env python3
                            import sys
                                
                            print("Ecrivez plusieurs noms de fruits non à la suite..")
                            print("Quand vous aurez fini cliquez sur CTRL+D")
                            fruits = sys.stdin.readlines()
                                
                            print("Vous avez saisi les fruits suivants:")
                            for fruit in fruits:
                                print(fruit.strip())
                                    
                            # Lecture plus simple :

                            fruit = input("Entrez un nom de fruit : ")
                            print(f"Vous avez saisi le fruit : {fruit}")

                            exit(0)
                            
                            
emoji_objects

- strip : cela supprime les espaces blancs éventuels.

Exécution
                            
                            mahmoud@Mahmoud:/script_python$ python3 s_4.py
                                Ecrivez plusieurs noms de fruits non à la suite..
                                Quand vous aurez fini cliquer sur CTRL+D
                                Pomme
                                Orange
                                Bannane
                                Vous avez saisi les fruits suivants:
                                Pomme
                                Orange
                                Bannane

                                Entrez un nom de fruit : Orange
                                Vous avez saisi le fruit : Orange
                            
                            

Les Fichiers

  Ouverture d'un fichier

En Python il existe la commande open pour ouvrir et manipuler les fichiers. La commande open prend en paramètre le nom du fichier, le flag d'accès à ce fichier [r,w,a(append)]. On termine notre opération par la fermeture du fichier avec fd.close()

                                
                                #!/usr/bin/env python3
                                import sys
                                    
                                # Vérification de l'argument
                                if len(sys.argv) <= 1:
                                    sys.stderr.write("Vous devez indiquer un nom de fichier en argument.\n")
                                    exit(1)
                                    
                                file = sys.argv[1]      # Récupération du nom du fichier
                                fd = open(file, 'r')    # Ouverture du fichier en mode lecture
                                content = fd.read()     # Lecture du fichier
                                print(content)          # Affichage du contenu du fichier
                                    
                                fd.close()              # Fermeture du fichier
                                exit(0)
                                
                                
Exécution
                                
                                mahmoud@Mahmoud:/script_python$  python3 s_6.py file.txt
                                    Orange
                                    Bannane
                                    Pomme
                                    Clémentine
                                    Mandarine
                                
                                
  Lectures d'un fichier
emoji_objects

Modes de lecture :
- read(taille) : Si on indique aucune taille il lira tout le fichier.
- readlines : Cette méthode lit toutes les lignes d'un fichier et les retourne sous forme de liste.
- readline : Est utilisée pour lire une seule ligne à partir d'un fichier. À chaque appel de readline(), elle lit la ligne suivante.

readlines
readline
readline Nième ligne

Exemple d'utilisation de readlines :

                                            
                                            #!/usr/bin/env python3
                                            import sys
                                                
                                            file = sys.argv[1]     
                                            fd = open(file, 'r')    
                                            content = fd.readlines()    
                                            print(content)         
                                                
                                            fd.close()              
                                            exit(0)
                                            
                                            
Exécution
                                            
                                            mahmoud@Mahmoud:/script_python$ python3 s_7.py file.txt
                                                ['Orange\n', 'Bannane\n', 'Pomme\n', 'Clémentine\n', 'Mandarine']
                                            
                                            

Exemple d'utilisation de readline, lecture de la première ligne :

                                            
                                            #!/usr/bin/env python3
                                            import sys
                                                
                                            file = sys.argv[1]     
                                            fd = open(file, 'r')    
                                            content = fd.readline()    
                                            print(content)         
                                                
                                            fd.close()              
                                            exit(0)                 
                                            
                                            
Exécution
                                            
                                            mahmoud@Mahmoud:/script_python$ python3 s_8.py file.txt
                                                Orange
                                                # + le retour à la ligne
                                            
                                            

Exemple d'utilisation de readline, pour lire la N ième ligne :

                                            
                                            #!/usr/bin/env python3
                                            import sys
                                                
                                            file = sys.argv[1]     
                                            fd = open(file, 'r')    
                                                
                                            print("Lecture de la première ligne :")
                                                
                                            fd.seek(0)  # Retour au début du fichier
                                            premiere_ligne = fd.readline()
                                            print("Première ligne : ", premiere_ligne) 
                                                
                                            print("Lecture de la cinquième  ligne :")
                                            fd.seek(0)          # Retour au début du fichier
                                            for _ in range(4):  # On saute les 4 premières lignes
                                                fd.readline()
                                            cinquieme_ligne = fd.readline()
                                            print("Cinquième ligne:", cinquieme_ligne)
                                                    
                                            fd.close()              
                                            exit(0)           
                                            
                                            
Exécution
                                            
                                            mahmoud@Mahmoud:/script_python$ python3 s_9.py file.txt
                                                Lecture de la première ligne :
                                                Première ligne :  Orange
                                                
                                                Lecture de la cinquième  ligne :
                                                Cinquième ligne: Mandarine
                                            
                                            
  Ecriture dans un fichier
emoji_objects

Modes d'écritures :
- write : Écriture d'une seule ligne dans un fichier
- writelines(lignes) : Écriture de plusieurs lignes dans un fichier. lignes est une liste.
- mode 'a' : Ajout de contenu à un fichier existant

write
writelines
write 'a'
emoji_objects

- En mode 'w', si le fichier existe déjà son contenu sera écrasé.

                                            
                                            #!/usr/bin/env python3

                                            with open('fichier.txt', 'w') as fichier:
                                                octets = fichier.write("Ceci est une ligne dans un fichier.\n")
                                                print(f"{octets} octets écris.")
                                                exit(0)
                                            
                                            
Exécution
                                            
                                            mahmoud@Mahmoud:/script_python$ python3 s_10.py
                                                36 octets écris.
                                            
                                            
emoji_objects

- writelines ne retourne pas le nombre d'octets écris.

                                            
                                            #!/usr/bin/env python3
                                            with open('fichier2.txt', 'w') as fichier:
                                                lignes = ["Première ligne\n", "Deuxième ligne\n", "Troisième ligne\n"]
                                                fichier.writelines(lignes)        
                                                exit(0)                 
                                            
                                            
Exécution
                                            
                                            mahmoud@Mahmoud:/script_python$ python3 s_11.py
                                            
                                            

Exemple d'utilisation de readline, pour lire la N ième ligne :

                                            
                                            #!/usr/bin/env python3
                                            with open('fichier.txt', 'a') as fichier:
                                                octets =fichier.write("Ceci est une nouvelle ligne ajoutée au fichier.\n")
                                                print(f"{octets} octets écris.")           
                                                exit(0)           
                                            
                                            
Exécution
                                            
                                            mahmoud@Mahmoud:/script_python$ python3 s_12.py
                                                48 octets écris.
                                            
                                            

Le Système de Fichier

Python nous permet de créer facilement des scripts qui intéragissent avec le système de fichier tel que les répertoires.
On peut en trautre :

  • Modifier les propriétés des fichiers
  • Obtention du répertoire racine, courant...
  • Création de répertoire, suppression...

Nous utiliserons le package : os.path, ainsi que les bibliothèques : shutil filecmp

  Opérations sur les répertoires

Nous allons voir des scripts qui manipule les répertoires où s'exécute le script.

os.chdir
os.listdir
os.mkdir

Changement de répertoire :

                                        
                                        #!/usr/bin/env python3
                                        import os
                                        
                                        # Changement du répertoire de travail pour le répertoire parent du répertoire courant.
                                        os.chdir("..")          
                                        exit(0)
                                        
                                        

Liste l'ensemble des fichiers et répertoire du répertoire courant

                                        
                                        #!/usr/bin/env python3
                                        import os
                                            
                                        fic = os.listdir("./")
                                        for i in fic:
                                            print(i)   

                                        exit(0)                 
                                        
                                        
Exécution
                                        
                                        mahmoud@Mahmoud:/script_python$ python3 s_12_rep.py
                                            fichier.txt
                                            fichier2.txt
                                            file.txt
                                            s_1.py
                                            s_10.py
                                            s_11_rep.py
                                            s_12_rep.py
                                            s_2.py
                                            s_3.py
                                            s_4.py
                                            s_5.py
                                            s_6.py
                                            s_7.py
                                            s_8.py
                                            s_9.py
                                        
                                        

Création d'un répertoire passé en argument :

                                        
                                        #!/usr/bin/env python3
                                        # -*- coding: utf-8 -*-
                                        import sys
                                        import os     
                                            
                                        try:
                                            os.mkdir(sys.argv[1])
                                        except Exception as e:  
                                            print(f"Erreur création du nouveau répertoire : {e}")
                                            exit(1)
                                        exit(0)  
                                        
                                        
Exécution
                                        
                                        mahmoud@Mahmoud:/script_python$ python3 s_13_rep.py test45
                                        
                                        
  shutil

Ce premier script démontrera comment utiliser shutil pour copier un fichier d'un emplacement à un autre.

                                
                                #!/usr/bin/env python3
                                import shutil
                                import os

                                source_file = 'source.txt'      # Nom du fichier source à copier
                                destination_dir = 'backup/'     # Dossier de destination

                                # Je vérifie si le répertoire de destination existe, sinon je le crée
                                if not os.path.exists(destination_dir):
                                    os.makedirs(destination_dir)

                                # Chemin complet du fichier de destination
                                destination_file = os.path.join(destination_dir, os.path.basename(source_file))

                                # Je copie le fichier seulement s'il n'existe pas déjà dans le répertoire de destination
                                if not os.path.exists(destination_file):
                                    shutil.copy(source_file, destination_dir)
                                    print(f"Le fichier {source_file} a été copié vers {destination_dir}")
                                else:
                                    print(f"Le fichier {source_file} existe déjà dans le répertoire de destination.")

                                exit(0)
                                
                                
Exécution
                                
                                mahmoud@Mahmoud:/script_python$ python3 s_14_rep.py s_1.py
                                Le fichier s_1.py a été copié vers backup/
                                
                                
  filecmp

Cet exemple permet de faire une comparaison entre deux fichiers :

                                
                                #!/usr/bin/env python3
                                import filecmp
                                import sys

                                fichier_1 = sys.argv[1]
                                fichier_2 = sys.argv[2]
                                res = filecmp.cmp(fichier_1, fichier_2)
                                if res:
                                    print("Les fichiers sont identiques.")
                                else:
                                    print("Les fichiers ne sont pas identiques.")
                                exit(0)
                                
                                
Exécution
                                
                                mahmoud@Mahmoud:/script_python$ python3 s_16_rep.py s_9.py s_10.py
                                    Les fichiers ne sont pas identiques.
                                mahmoud@Mahmoud:/script_python$ python3 s_16_rep.py s_9.py s_9.py
                                    Les fichiers sont identiques.
                                
                                
  os.path.isfile

Cet exemple permet de vérifier que un nom de fichier passé en argument est vraiment un fichier :

                                
                                #!/usr/bin/env python3
                                import sys
                                import os
                                    
                                fichier = sys.argv[1]
                                    
                                if os.path.isfile(fichier):
                                    print("C'est un fichier.")
                                else:
                                    print("Ce n'est pas un fichier.")
                                    
                                exit(0)
                                
                                
Exécution
                                
                                mahmoud@Mahmoud:/script_python$ python3 s_17_rep.py s_9.py
                                    C'est un fichier.
                                mahmoud@Mahmoud:/script_python$ python3 s_16_rep.py backup/
                                    Ce n'est pas un fichier.
                                
                                
  os.path.isdir

Cet exemple permet de vérifier que le nom reçu en argument est bien un répertoire :

                                
                                #!/usr/bin/env python3
                                import sys
                                import os
                                        
                                rep = sys.argv[1]
                                    
                                if os.path.isdir(rep):
                                    print("C'est un répertoire.")
                                else:
                                    print("Ce n'est pas un répertoire.")
                                        
                                exit(0)
                                
                                
Exécution
                                
                                mahmoud@Mahmoud:/script_python$ python3 s_18_rep.py backup/
                                    C'est un répertoire.
                                mahmoud@Mahmoud:/script_python$ python3 s_18_rep.py s_1.py
                                    Ce n'est pas un répertoire.
                                
                                

Exécution de commandes système

Python dispose de bibliothèque et package pour exécuter des commandes système depuis un script.

  Subprocess
  • Subprocess : Le module subprocess de Python permet d'exécuter des commandes système et de contrôler des processus externes depuis un script Python.
  • subprocess.Popen : est une fonction du module subprocess qui lance un nouveau processus externe avec les paramètres spécifiés et permet au script Python de communiquer avec ce processus et de contrôler son exécution.
  • subprocess.run : est une autre fonction du module subprocess qui est souvent recommandée pour remplacer subprocess.Popen dans les cas simples où l'on souhaite juste exécuter une commande et attendre sa fin. Elle offre une interface plus simple et plus sûre pour exécuter des commandes système à partir de Python.
  Subprocess.Popen
Sans sudo
Avec sudo

Exemple de script Python qui exécute la commande ls -al dans un processus externe.

                                            
                                            #!/usr/bin/env python3
                                            import subprocess
                                                
                                            p = subprocess.Popen(["ls", "-al"], stdout=subprocess.PIPE)
                                            print(p.communicate())
                                            exit(0)              
                                            
                                            
emoji_objects

- Ligne 3 : Cette ligne exécute la commande ls -al dans un processus externe et récupère sa sortie standard. Le résultat est stocké dans l'objet p.
- print(p.communicate()) : Cette ligne imprime la sortie du processus créé précédemment à l'aide. Cette méthode renvoie un tuple contenant la sortie standard et la sortie d'erreur du processus. Dans ce cas, seule la sortie standard est imprimée.

Cet exemple montre comment utiliser Popen pour lancer une commande qui demande des privilèges élevés.

                                            
                                            # -*- coding: utf-8 -*-
                                            #!/usr/bin/env python3
                                            import subprocess

                                            command = "sudo mkdir test_sudo"

                                            # Utilisation de subprocess.Popen() pour exécuter la commande
                                            try:
                                                process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                                                stdout, stderr = process.communicate()  # Récupérer la sortie standard et d'erreur

                                                if process.returncode == 0:
                                                    print("La commande a été exécutée avec succès.")
                                                else:
                                                    print(f"La commande a échoué avec le code de retour {process.returncode}.")
                                                    print("Sortie standard :")
                                                    print(stdout.decode())
                                                    print("Sortie d'erreur :")
                                                    print(stderr.decode())
                                            except Exception as e:
                                                print(f"Une erreur s'est produite lors de l'exécution de la commande : {e}")

                                            exit(0)
                                            
                                            
content_copy
  Subprocess.run

Exemple de script Python qui exécute la commande ls -al dans un processus externe.

                                
                                #!/usr/bin/env python3
                                import subprocess

                                # J'exécute la commande 'ls -al' et je capture la sortie
                                result = subprocess.run(['ls', '-al'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

                                # J'affiche la sortie de la commande
                                if result.returncode == 0:
                                    print("Sortie de la commande 'ls':\n", result.stdout)
                                else:
                                    print("Erreur lors de l'exécution de 'ls':\n", result.stderr)
                                    exit(1)
                                exit(0)
                                
                                
emoji_objects

- text=True : Ce paramètre sert à indiquer que les données échangées entre le processus principal et le processus enfant doivent être traitées comme des chaînes de caractères (texte), plutôt que des bytes.

  Subprocess.run avec shell=True

L'option shell=True dans subprocess.run() permet d'exécuter la commande à travers un shell interpréteur, ce qui te donne accès aux fonctionnalités du shell comme les tubages et les redirections.
Cependant, cela peut être moins sûr à cause du risque d'injection de commandes si la commande est construite à partir d'entrées utilisateur. Sans shell=True, la commande est exécutée directement sans interpréteur de shell, ce qui est plus sûr et légèrement plus performant pour des commandes simples.
L'option check=True est utilisée en conjonction avec shell=True dans un appel à subprocess.run() fait que Python lèvera une exception subprocess.CalledProcessError si la commande exécutée renvoie un code de sortie non nul

                                
                                #!/usr/bin/env python3
                                import subprocess

                                try:
                                    # Lève une exception si la commande échoue
                                    subprocess.run('ls -l', shell=True, check=True)
                                except subprocess.CalledProcessError as e:
                                    print(f"Erreur: La commande a échoué avec le code de retour {e.returncode}")
                                    exit(1)

                                exit(0)
                                
                                
emoji_objects

Dans cet exemple, shell=True permet d'utiliser les fonctionnalités du shell pour exécuter la commande, et check=True assure que toute erreur dans l'exécution de la commande provoque l'arrêt de ton script en levant une exception.

Expréssions régulières

Le module re en Python est spécialement dédié à la manipulation des expressions régulières, mais il propose plusieurs fonctionnalités qui dépassent le simple usage des expressions régulières en elles-mêmes. Voici quelques-unes des caractéristiques et fonctionnalités supplémentaires du module re :

- Compilation des expressions régulières : Les expressions régulières peuvent être compilées en objets de motif à l'aide de re.compile().

- Groupes de capture : Le module re permet de définir des groupes de capture à l'intérieur des expressions régulières, facilitant ainsi la récupération de parties spécifiques d'une chaîne correspondante pour un traitement ultérieur.

- Flags : Le module re permet l'utilisation de flags qui modifient certains aspects de la correspondance des expressions régulières, tels que la sensibilité à la casse re.IGNORECASE, le mode multiligne re.MULTILINE, et le mode point-tout re.DOTALL.

- Méthodes de correspondance multiples : En plus de re.search(), qui recherche une correspondance n'importe où dans la chaîne.

- re.match() : recherche qu'au début de la chaîne.

- re.fullmatch() : exige que toute la chaîne corresponde.

- re.findall() et re.finditer() : retournent toutes les correspondances non chevauchantes sous forme de listes ou d'itérateurs.

- Substitution re.sub() re.subn() : permettent de remplacer des textes dans une chaîne qui correspondent à une expression régulière.

- Division de chaîne re.split() : il est possible de diviser une chaîne en utilisant une expression régulière comme délimiteur, offrant ainsi une méthode plus puissante que la méthode split() intégrée des chaînes.

- Échappement de caractères re.escape() : peut être utilisé pour échapper tous les caractères spéciaux dans une chaîne, afin qu'ils soient traités littéralement dans les expressions régulières.

Des exemples sont illustrés ci-dessous :

re.compile
groupe re.compile
Flags
correspondance multiples
Substitution
Division de chaîne
Échappement de caractères

Ce script compile d'abord une expression régulière qui recherche des séquences de chiffres (\d+).

                                        
                                        #!/usr/bin/env python3
                                        import re

                                        # Compilation de l'expression régulière
                                        pattern = re.compile(r'\d+')  # Trouver des séquences de chiffres
                                            
                                        # Utilisation de l'objet de motif compilé pour rechercher dans une chaîne
                                        match = pattern.search('Le numéro est 12345')
                                        if match:
                                            print(match.group())  # Affiche '12345'
                                        exit(0)
                                        
                                        

Ce script démontre l'utilisation des groupes de capture pour extraire des informations spécifiques d'une chaîne de caractères. Il compile d'abord une expression régulière qui capture l'année, le mois et le jour d'une date au format YYYY-MM-DD. Ensuite, il recherche dans une chaîne donnée et affiche les informations extraites si une correspondance est trouvée.

                                        
                                        #!/usr/bin/env python3
                                        import re

                                        # Utilisation des groupes de capture pour
                                        # extraire des informations spécifiques
                                        date_pattern = re.compile(r'(\d{4})-(\d{2})-(\d{2})')  # Capture l'année, le mois, et le jour
                                        match = date_pattern.search('La date est 2024-02-24')
                                        if match:
                                            print(f"Année: {match.group(1)}, Mois: {match.group(2)}, Jour: {match.group(3)}")
                                        exit(0)         
                                        
                                        

Ce code Python montre l'utilisation des flags pour modifier le comportement des expressions régulières lors de la recherche dans une chaîne de caractères. Il utilise le drapeau re.IGNORECASE pour ignorer la casse lors de la recherche du mot "python" dans une chaîne. De plus, il utilise le drapeau re.MULTILINE pour effectuer une recherche en mode multiligne afin de trouver le mot "python" uniquement au début de chaque ligne.

                                        
                                        #!/usr/bin/env python3
                                        import re

                                        # Utilisation de flags
                                        case_insensitive = re.search('python', 'Je code en Python', re.IGNORECASE)
                                        if case_insensitive:
                                            print('Trouvé en ignorant la casse:', case_insensitive.group())

                                        multiline = re.compile(r'^python', re.MULTILINE)
                                        multi_match = multiline.search('test\npython\nPython', re.IGNORECASE)
                                        if multi_match:
                                            print('Trouvé en mode multiligne:', multi_match.group())
                                        exit(0)  
                                        
                                        

Ce script illustre plusieurs fonctionnalités du module re. Il utilise re.match() pour rechercher un motif au début de la chaîne, re.fullmatch() pour trouver une correspondance complète avec toute la chaîne, et re.findall() et re.finditer() pour trouver toutes les occurrences de motifs dans une chaîne.

                                        
                                        #!/usr/bin/env python3
                                        import re

                                        match_example = re.match('www', 'www.example.com')
                                        print('Match:', match_example.group())

                                        # re.fullmatch()
                                        full_match_example = re.fullmatch(r'\d+', '12345')
                                        print('Full match:', full_match_example.group())

                                        # re.findall() et re.finditer()
                                        findall_example = re.findall(r'\d+', '12 abc 34 def 56 ghi')
                                        print('Findall:', findall_example)

                                        finditer_example = [match.group() for match in re.finditer(r'\d+', '12 abc 34 def 56 ghi')]
                                        print('Finditer:', finditer_example)
                                        exit(0)
                                        
                                        

Ce code Python montre l'utilisation de re.sub() pour remplacer tous les motifs correspondants dans une chaîne par une chaîne de remplacement spécifiée, et re.subn() pour obtenir à la fois la nouvelle chaîne avec les remplacements et le nombre total de remplacements effectués.

                                        
                                        #!/usr/bin/env python3
                                        import re

                                        sub_example = re.sub(r'\d+', 'number', '12 abc 34 def 56 ghi')
                                        print('Sub:', sub_example)

                                        # re.subn()
                                        subn_example, n = re.subn(r'\d+', 'number', '12 abc 34 def 56 ghi')
                                        print('Subn:', subn_example, 'Nombre de remplacements:', n)

                                        exit(0)  
                                        
                                        

Ce code Python utilise re.split() pour diviser une chaîne en une liste de sous-chaînes en utilisant une expression régulière comme délimiteur. Dans cet exemple, la chaîne est divisée en mots en utilisant \W+ comme motif de délimitation, ce qui signifie que tout caractère non-alphabétique est utilisé comme délimiteur.

                                        
                                        #!/usr/bin/env python3
                                        import re

                                        split_example = re.split(r'\W+', 'Words, words, words.')
                                        print('Split:', split_example)

                                        exit(0)  
                                        
                                        

Ce code Python utilise re.escape() pour échapper tous les caractères spéciaux dans une chaîne de caractères, afin qu'ils soient traités littéralement dans les expressions régulières. Dans cet exemple, la chaîne '3.5$ per item' est échappée, ce qui signifie que le caractère $ est échappé pour qu'il soit traité littéralement dans une expression régulière.

                                        
                                        #!/usr/bin/env python3
                                        import re

                                        to_search = '3.5$ per item'
                                        escaped_string = re.escape(to_search)
                                        print('Escaped:', escaped_string)

                                        exit(0)  
                                        
                                        
Vérification du nombre d'argument

On doit toujours vérifier qu'on reçoit bien le bon nombres d'arguments :

Shell
Python
                                        
                                        #!/bin/bash
    
                                        # Vérification du nombre de paramètres
                                        if [ $# -eq 0 ]; then
                                            echo "Je dois utiliser ce script comme suit: $0 <votre_prenom>"
                                            exit 1
                                        fi
                                            
                                        prenom=$1

                                        echo "Bonjour "$prenom" nous somme le :" $(date)
                                        exit 0
                                        
                                        
content_copy
                                        
                                        # -*- coding: utf-8 -*-
                                        #!/usr/bin/env python3
                                        
                                        import sys
                                        from datetime import datetime
                                        
                                        # Vérification du nombre de paramètres
                                        if len(sys.argv) <= 1:
                                            print(f"Je dois utiliser ce script comme suit: {sys.argv[0]} <votre_prenom>")
                                            sys.exit(1)
                                        
                                        # Affichage du message
                                        prenom = sys.argv[1]
                                        print(f"Bonjour {prenom}, nous sommes le : {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
                                        
                                        sys.exit(0)
                                        
                                        
content_copy
Appel système

Lorsqu'on exécute une commande système, on doit toujours vérifier si elle a bien été exécutée.

Shell
Python
                                        
                                        #!/bin/bash

                                        # Exécute la commande apt install par exemple
                                        apt install <package_name>
                                            
                                        # Vérifie le code de retour de la commande
                                        if [ $? -ne 0 ]; then
                                            # En cas d'erreur, affiche un message d'erreur et quitte avec un code de sortie non nul
                                            echo "Erreur lors de l'installation du paquet."
                                            exit 1
                                        else
                                            # Si la commande s'est exécutée avec succès, affiche un message de réussite
                                            echo "Installation du paquet terminée avec succès."
                                        fi
                                        
                                        
content_copy
                                        
                                        # -*- coding: utf-8 -*-
                                        #!/usr/bin/env python3
                                        
                                        import sys
                                        import subprocess

                                        package_name = "<package_name>"

                                        try:
                                            # Exécute la commande apt install
                                            result = subprocess.run(["sudo", "apt", "install", package_name], check=True)

                                            # Si la commande s'est exécutée avec succès, affiche un message de réussite
                                            print("Installation du paquet terminée avec succès.")
                                        except subprocess.CalledProcessError:
                                            # En cas d'erreur, affiche un message d'erreur et quitte avec un code de sortie non nul
                                            print("Erreur lors de l'installation du paquet.")
                                            exit(1)

                                        sys.exit(0)
                                        
                                        
content_copy
Exécution d'un script en tant que root

Certains scripts doivent être exécutés en tant que root. Il est essentiel de vérifier cela avant de lancer le script :

Shell
Python
                                        
                                        #!/bin/bash

                                        # Vérification si le script est lancé avec les privilèges root
                                        if [ "$EUID" -ne 0 ]; then
                                            echo -e "\e[31mErreur :\e[0m Ce script doit être exécuté en tant que root."
                                            exit 1
                                        fi
                                        
                                        echo "Script lancé en tant que root."
                                        
                                        
content_copy
                                        
                                        # -*- coding: utf-8 -*-
                                        #!/usr/bin/env python3

                                        import os
                                        import sys

                                        # Vérification si le script est lancé avec les privilèges root
                                        if os.geteuid() != 0:
                                            print("\033[31mErreur :\033[0m Ce script doit être exécuté en tant que root.")
                                            sys.exit(1)

                                        print("Script lancé en tant que root.")
                                        sys.exit(0)
                                        
                                        
content_copy