Objectifs
- Capturer la sortie d’une commande dans une variable en utilisant
$(...). - Comprendre pourquoi la syntaxe moderne
$(...)est supérieure aux backticks (`...`). - Découvrir la substitution de processus
<(...)pour utiliser la sortie d’une commande comme un fichier.
Explications détaillées
Notions clés
Substitution de Commande : $(...)
La substitution de commande est un mécanisme qui permet d’exécuter une commande et de récupérer sa sortie standard (stdout) pour l’utiliser comme une chaîne de caractères (dans une variable, comme argument d’une autre commande, etc.).
Le shell voit $(une_commande), il exécute une_commande, capture ce qu’elle affiche, et remplace toute l’expression $(...) par ce texte.
L’ancienne syntaxe : les Backticks `...`
Avant $(...), on utilisait les backticks (apostrophes inverses).
MA_VAR=une_commande```
Cette syntaxe fonctionne mais est dépréciée car :
- Elle est moins lisible (facile à confondre avec les guillemets simples
'). - Elle ne s’imbrique pas bien.
echoecho lackpwdlackest un cauchemar à lire.echo $(echo $(pwd))est parfaitement clair.
Règle simple : n’utilisez jamais les backticks dans de nouveaux scripts.
Substitution de Processus : <(...)
C’est une fonctionnalité plus avancée mais extrêmement puissante. Elle exécute une commande et fait en sorte que sa sortie se comporte comme un fichier temporaire.
Ceci est utile pour les commandes qui attendent des noms de fichiers en argument, comme diff, join, ou paste.
diff <(commande1) <(commande2): Compare la sortie decommande1avec celle decommande2sans avoir à créer de vrais fichiers sur le disque.
Syntaxe / Usages
# Capturer la date dans une variable
DATE_DU_JOUR=$(date +%Y-%m-%d)
echo "Date: $DATE_DU_JOUR"
# Créer un nom de fichier unique basé sur la date et l'heure
nom_log="rapport-$(date +%Y%m%d_%H%M%S).log"
touch "$nom_log"
# Compter le nombre de fichiers dans le répertoire courant
nb_fichiers=$(ls | wc -l)
echo "Il y a $nb_fichiers fichiers ici."
# Imbrication : obtenir le nom du dossier contenant le script courant
dossier_script=$(dirname "$(realpath "$0")")
echo "Le script se trouve dans: $dossier_script"
# Comparer deux listes triées sans fichiers intermédiaires
diff <(sort liste1.txt) <(sort liste2.txt)
Exemples
# 1. Créer un dossier de sauvegarde avec la date
# On capture la date au format YYYY-MM-DD
dossier_backup="backup-$(date +%F)"
mkdir "$dossier_backup"
echo "Dossier de sauvegarde créé : $dossier_backup"
# 2. Utiliser la sortie d'une commande comme partie d'une autre
# Affiche "Il y a X utilisateurs connectés"
echo "Il y a $(who | wc -l) utilisateurs connectés."
# 3. Attention aux guillemets !
# La commande 'ls -l' produit plusieurs lignes
sortie_ls=$(ls -l)
# Sans guillemets, les sauts de ligne sont perdus et tout est sur une seule ligne
echo $sortie_ls
# Avec guillemets, la mise en forme est préservée
echo "$sortie_ls"
Bonnes pratiques
- Toujours utiliser
$(...), jamais les backticks`...`. - Toujours mettre la substitution entre guillemets doubles (
"$(...)"). C’est essentiel pour préserver les espaces et les sauts de ligne, et éviter que le shell n’interprète mal la sortie. - La substitution de processus
<(...)est parfaite pour éviter de créer des fichiers temporaires, ce qui rend les scripts plus propres et plus efficaces.
Pièges courants
- Oublier les guillemets : C’est le piège le plus fréquent.
ma_var=$(ls -l)puisecho $ma_varperd toute la mise en forme.echo "$ma_var"la conserve. - Capturer une sortie énorme : Si la commande produit des gigaoctets de données, tout capturer dans une variable peut saturer la mémoire. Dans ce cas, il vaut mieux utiliser des pipes
|. - Ne capturer que stdout : La substitution de commande ignore par défaut
stderr. Si vous voulez capturer les erreurs aussi, il faut les rediriger :sortie_complete=$(commande 2>&1).
Exercices
-
Variable dynamique :
- Créez une variable
NOWqui contient la date et l’heure actuelles au formatHH:MM:SS. - Affichez “Il est exactement : [valeur de NOW]”.
- Créez une variable
-
Script de sauvegarde :
- Écrivez un script
backup.shqui crée une archivetarde votre dossierDocuments. - Le nom de l’archive doit être
sauvegarde-documents-YYYY-MM-DD.tar.gz. Utilisez la substitution de commande pour la date.
- Écrivez un script
-
Comparaison sans fichiers (avancé) :
- Créez deux listes de noms dans deux fichiers,
equipe_A.txtetequipe_B.txt, avec certains noms en commun. - En une seule ligne de commande, en utilisant
diffet la substitution de processus, affichez les différences entre les deux équipes après les avoir triées.
- Créez deux listes de noms dans deux fichiers,