Objectifs
- Comprendre ce qu’est un subshell (sous-shell) et dans quelles situations il est créé.
- Utiliser les parenthèses
(...)pour exécuter un groupe de commandes dans un environnement isolé. - Visualiser l’impact des subshells sur la portée des variables et le répertoire courant.
- Distinguer le groupement par parenthèses
()(subshell) du groupement par accolades{...}(shell courant).
Explications détaillées
Notions clés
Qu’est-ce qu’un subshell ?
Un subshell est un nouveau processus lancé par votre shell principal. C’est une sorte de “clone” temporaire de votre shell.
- Héritage : Il hérite d’une copie des variables d’environnement du shell parent.
- Isolation : C’est le point crucial. Toutes les modifications effectuées à l’intérieur du subshell (changement de répertoire avec
cd, modification de variable) sont confinées à ce subshell. Une fois le subshell terminé, ces changements sont perdus et le shell parent n’est pas affecté.
Quand un subshell est-il créé ?
Automatiquement dans plusieurs situations courantes :
- Parenthèses
(...): C’est la manière la plus explicite de créer un subshell.( commande1; commande2 ) - Pipelines
|: Chaque commande dans un pipeline s’exécute dans son propre subshell. - Substitution de commande
$(...): La commande à l’intérieur est exécutée dans un subshell. - Commande en arrière-plan
&: La commande est lancée dans un subshell séparé.
() vs {} : Subshell vs Groupement
( ... ): Les commandes s’exécutent dans un subshell. Les changements sont temporaires.{ ...; }: Les commandes sont simplement groupées mais s’exécutent dans le shell courant. Les changements sont persistants. Notez l’espace après{et le point-virgule;(ou un saut de ligne) avant}.
Syntaxe / Usages
# Lancer des commandes dans un subshell pour isoler les changements
(
echo "Entrée dans le subshell. PWD: $(pwd)"
cd /tmp
echo "Changé de dossier. PWD: $(pwd)"
) # Le subshell se termine ici
# De retour dans le shell parent, le PWD n'a pas changé
echo "Retour dans le parent. PWD: $(pwd)"
# Groupement avec des accolades (pas de subshell)
{
echo "Début du groupe."
cd /tmp
echo "Changé de dossier dans le groupe. PWD: $(pwd)"
} # Le groupe se termine
# Le changement de PWD persiste
echo "Après le groupe. PWD: $(pwd)"
Exemples
# 1. Le piège classique du pipeline
# On veut compter les lignes d'un fichier et stocker le compte
compteur=0
cat mon_fichier.txt | while read -r ligne; do
((compteur++))
done
# La boucle 'while' s'exécute dans un subshell. 'compteur' est copié,
# incrémenté dans le subshell, puis détruit.
echo "Nombre de lignes : $compteur" # -> Affiche 0 !
# La solution : éviter le pipe vers 'while'
compteur=0
while read -r ligne; do
((compteur++))
done < mon_fichier.txt # Redirection d'entrée, pas de subshell pour la boucle
echo "Nombre de lignes : $compteur" # -> Affiche le bon nombre
# 2. Utiliser un subshell pour des opérations temporaires
# Supposons que nous voulions construire un projet dans un autre dossier
# sans avoir à faire 'cd ..' pour revenir.
echo "Compilation du projet..."
(
cd ./projet_source/
./configure
make
) # Fin du subshell, nous sommes de retour où nous étions.
echo "Compilation terminée."
Bonnes pratiques
- Utilisez les subshells avec
()de manière intentionnelle pour isoler des actions. C’est parfait pour changer de répertoire temporairement ou pour définir des variables qui ne doivent pas “fuiter” dans le reste du script. - Soyez conscient que les pipelines créent des subshells. C’est une source de bugs fréquente pour les débutants qui essaient de modifier des variables dans une boucle
whilealimentée par un pipe. - Préférez la redirection d’entrée (
while ... < fichier) àcat fichier | while ...pour éviter le subshell inutile.
Pièges courants
- Modification de variable dans un pipe : Tenter de modifier une variable dans une boucle
whilequi fait partie d’un pipeline. La modification sera perdue. - Performance : Lancer un subshell a un léger coût (création d’un nouveau processus). Pour des milliers de petites opérations dans une boucle, un groupement
{}peut être plus performant, mais seulement si vous n’avez pas besoin de l’isolation.
Exercices
-
Isolation de
cd:- Écrivez un script qui :
- Affiche le répertoire courant (
pwd). - Utilise un subshell
()pour se déplacer dans/et lister son contenu. - Affiche à nouveau le répertoire courant pour prouver que le
cdétait temporaire.
- Affiche le répertoire courant (
- Écrivez un script qui :
-
Le compteur qui ne compte pas :
- Créez un fichier
nombres.txtavec 5 lignes. - Écrivez un script qui tente de compter les lignes en utilisant
cat nombres.txt | while read -r line; do ((count++)); done. - Affichez la variable
countaprès la boucle et constatez qu’elle est à 0.
- Créez un fichier
-
Le compteur qui compte :
- Corrigez le script de l’exercice précédent en utilisant une redirection d’entrée pour que la boucle
whiles’exécute dans le shell principal. - Vérifiez que la variable
counta maintenant la bonne valeur.
- Corrigez le script de l’exercice précédent en utilisant une redirection d’entrée pour que la boucle