Introduction
Un script shell regroupe des commandes dans un fichier afin de pouvoir répéter une tâche de manière fiable et cohérente. Pour être robustes, les scripts destinés aux débutants doivent indiquer explicitement leur interpréteur, protéger les expansions de variables avec des guillemets, vérifier les entrées avant d’agir et renvoyer un statut de sortie compréhensible par les autres commandes.
Dans ce laboratoire, vous allez construire progressivement de petits scripts Bash. Vous les exécuterez avec Bash puis directement comme fichiers exécutables, utiliserez des variables et des arguments positionnels, lirez des entrées interactives, effectuerez des branchements avec if et des tests de fichiers, choisirez des codes de sortie, parcourrez des fichiers avec for, puis combinerez ces notions dans un script simple de synthèse de journaux.
Créer et exécuter votre premier script
Dans cette étape, vous allez créer un script Bash, l’exécuter via un interpréteur, puis le rendre directement exécutable.
Accédez à l’espace de travail du laboratoire :
cd /home/labex/project/shell-lab
Créez hello.sh à l’aide d’un document intégré. La première ligne est un shebang qui sélectionne Bash lorsque le fichier est exécuté directement :
cat > hello.sh <<'EOF'
#!/bin/bash
echo "Hello from a Bash script"
pwd
EOF
Examinez le fichier avant de l’exécuter :
cat hello.sh
Passez explicitement le fichier à Bash. Cela fonctionne même avant l’ajout du droit d’exécution :
bash hello.sh
Ajoutez le droit d’exécution et vérifiez le mode du fichier :
chmod u+x hello.sh
ls -l hello.sh
Exécutez le fichier depuis le répertoire courant. ./ fournit un chemin ; par défaut, le shell ne recherche pas automatiquement les commandes dans le répertoire courant :
./hello.sh
Utiliser des variables et des guillemets sûrs
Dans cette étape, vous allez affecter des variables, les développer et constater pourquoi les guillemets doubles protègent les valeurs contenant des espaces.
Créez un script avec deux variables :
cat > variables.sh <<'EOF'
#!/bin/bash
course="Linux for Noobs"
workspace="/home/labex/project/shell-lab"
echo "Course: $course"
echo "Workspace: $workspace"
printf 'Quoted argument count: %s\n' "$#"
printf 'First argument: %s\n' "${1:-not provided}"
EOF
Aucun espace ne doit entourer = lors d’une affectation shell. Les guillemets doubles permettent le développement de $course tout en conservant Linux for Noobs comme une seule valeur.
Exécutez le script avec un argument contenant des espaces :
bash variables.sh "beginner learner"
La variable spéciale $# contient le nombre d’arguments positionnels, tandis que $1 contient le premier argument. ${1:-not provided} fournit une valeur de remplacement lorsque le premier argument est absent.
Enregistrez la sortie pour l’examiner :
bash variables.sh "beginner learner" > variable-output.txt
cat variable-output.txt
Vérifier les arguments positionnels
Dans cette étape, vous allez rendre un argument obligatoire, afficher des indications d’utilisation et renvoyer des statuts de sortie différents en cas d’échec ou de réussite.
Créez greet-argument.sh :
cat > greet-argument.sh <<'EOF'
#!/bin/bash
if [ "$#" -ne 1 ]; then
echo "Usage: $0 NAME" >&2
exit 2
fi
name=$1
echo "Hello, $name"
exit 0
EOF
La commande de test [ ... ] vérifie que le nombre d’arguments est différent de un. >&2 envoie le texte d’utilisation vers la sortie d’erreur standard, tandis que exit 2 signale une utilisation incorrecte.
Exécutez le script sans argument, puis affichez immédiatement $?, qui contient le statut de sortie de la commande précédente :
bash greet-argument.sh
echo "missing argument status: $?"
Le statut attendu est 2. Exécutez ensuite le script correctement :
bash greet-argument.sh "Ada Lovelace"
echo "valid argument status: $?"
Enregistrez le message d’accueil produit avec succès :
bash greet-argument.sh "Ada Lovelace" > argument-greeting.txt
Lire une entrée interactive
Dans cette étape, vous allez inviter l’utilisateur à saisir une valeur, lire une ligne en toute sécurité et gérer le cas d’une entrée vide.
Créez ask-name.sh :
cat > ask-name.sh <<'EOF'
#!/bin/bash
read -r -p "Enter your name: " name
if [ -z "$name" ]; then
echo "A name is required" >&2
exit 1
fi
echo "Welcome, $name"
EOF
read -r lit une ligne sans traiter les antislashs de manière particulière. -p affiche une invite, et -z vérifie si la valeur entre guillemets est vide.
Exécutez le script :
bash ask-name.sh
À l’invite, saisissez :
Grace Hopper
Vous devriez voir Welcome, Grace Hopper. Pour obtenir un résultat reproductible et enregistré, transmettez une ligne d’entrée au même script :
printf 'Grace Hopper\n' | bash ask-name.sh > interactive-greeting.txt
cat interactive-greeting.txt
Effectuer des branchements avec des tests de fichiers
Dans cette étape, vous allez utiliser if, elif et else avec des tests de fichiers afin de déterminer la nature d’un chemin.
Créez classify-path.sh :
cat > classify-path.sh <<'EOF'
#!/bin/bash
path=${1:-}
if [ -z "$path" ]; then
echo "Usage: $0 PATH" >&2
exit 2
elif [ -d "$path" ]; then
echo "directory: $path"
elif [ -f "$path" ]; then
echo "file: $path"
else
echo "missing: $path" >&2
exit 1
fi
exit 0
EOF
-d vérifie s’il s’agit d’un répertoire et -f vérifie s’il s’agit d’un fichier ordinaire. L’ordre est important : l’utilisation incorrecte est traitée avant la détermination du type de chemin.
Testez les trois résultats possibles :
bash classify-path.sh logs
bash classify-path.sh notes.txt
bash classify-path.sh missing.txt
echo "missing path status: $?"
Enregistrez ensemble les résultats réussis. && n’exécute la seconde commande que si la première réussit :
bash classify-path.sh logs > path-results.txt && bash classify-path.sh notes.txt >> path-results.txt
cat path-results.txt
Traiter plusieurs fichiers avec une boucle For
Dans cette étape, vous allez parcourir des fichiers journaux et compter, dans chacun d’eux, les enregistrements correspondants.
Créez count-errors.sh :
cat > count-errors.sh <<'EOF'
#!/bin/bash
log_dir=${1:-logs}
if [ ! -d "$log_dir" ]; then
echo "Log directory not found: $log_dir" >&2
exit 1
fi
for log_file in "$log_dir"/*.log; do
error_count=$(grep -c '^ERROR ' "$log_file" || true)
printf '%s errors=%s\n' "$(basename "$log_file")" "$error_count"
done
EOF
À chaque itération, la boucle affecte à log_file l’un des chemins correspondants. Les guillemets autour de "$log_file" protègent les espaces, tandis que basename supprime le préfixe du répertoire. grep -c compte les lignes correspondantes ; || true évite qu’une absence de correspondance n’interrompe un traitement plus vaste exécuté en mode strict.
Exécutez la boucle et enregistrez sa sortie :
bash count-errors.sh logs | tee error-counts.txt
Vous devriez obtenir un résultat pour chaque fichier .log.
Combiner validation, boucles et statuts de sortie
Dans cette étape, vous allez créer un script réutilisable qui vérifie un répertoire, synthétise ses journaux et indique clairement la réussite ou l’échec de l’opération.
Créez summarize-logs.sh :
cat > summarize-logs.sh <<'EOF'
#!/bin/bash
input_dir=${1:-}
output_file=${2:-}
if [ -z "$input_dir" ] || [ -z "$output_file" ]; then
echo "Usage: $0 INPUT_DIR OUTPUT_FILE" >&2
exit 2
fi
if [ ! -d "$input_dir" ]; then
echo "Input directory not found: $input_dir" >&2
exit 1
fi
: > "$output_file"
for log_file in "$input_dir"/*.log; do
lines=$(wc -l < "$log_file")
errors=$(grep -c '^ERROR ' "$log_file" || true)
printf '%s lines=%s errors=%s\n' "$(basename "$log_file")" "$lines" "$errors" >> "$output_file"
done
echo "Wrote summary to $output_file"
exit 0
EOF
La commande : > "$output_file" crée la destination ou la vide proprement avant le début de la boucle. Exécutez le script avec les deux arguments obligatoires :
chmod u+x summarize-logs.sh
./summarize-logs.sh logs log-summary.txt
echo "summary status: $?"
cat log-summary.txt
Testez le scénario d’échec avec un répertoire inexistant :
./summarize-logs.sh missing log-summary.txt
echo "missing directory status: $?"
Le statut de réussite doit être 0, tandis que le statut associé au répertoire inexistant doit être 1.
Résumé
Vous avez créé et exécuté des scripts Bash, utilisé des shebangs et des permissions, développé des variables protégées par des guillemets, lu des entrées positionnelles et interactives, et renvoyé des statuts de sortie significatifs. Vous avez également effectué des branchements avec if/elif/else, testé des fichiers et des répertoires, parcouru des journaux avec for et combiné ces notions dans un script de synthèse réutilisable.
Ces notions fondamentales rendent les automatisations ultérieures plus faciles à lire, plus sûres à réexécuter et plus simples à évaluer pour d’autres commandes ou des tâches planifiées.



