Aller au contenu

Bash : redirections et pipes

Chaque programme dispose de trois flux : l’entrée (0), la sortie (1) et la sortie d’erreur (2). Les redirections et les pipes les connectent à des fichiers ou à d’autres commandes.

Écriture Effet
commande > fichier Écrit la sortie dans le fichier (écrase le contenu)
commande >> fichier Ajoute la sortie à la fin du fichier
commande < fichier Lit l’entrée depuis le fichier
commande 2> erreurs.log Écrit les erreurs dans un fichier
commande > tout.log 2>&1 Sortie et erreurs dans le même fichier
commande &> tout.log Forme courte de la précédente (Bash)
commande > /dev/null Jette la sortie normale
commande > /dev/null 2>&1 Jette la sortie et les erreurs
Fenêtre de terminal
ls /tmp > liste.txt # crée ou écrase liste.txt
date >> journal.log # ajoute une ligne
find / -name "*.conf" 2>/dev/null # masque les erreurs « Permission denied »
./script.sh > sortie.log 2> erreurs.log

L’ordre compte : > fichier 2>&1 est correct ; 2>&1 > fichier ne redirige pas les erreurs vers le fichier.

Fenêtre de terminal
echo "Erreur : fichier introuvable" >&2 # sort sur le flux d'erreur

Les messages d’erreur sur >&2 ne se mélangent pas avec la sortie utile quand celle-ci est redirigée ou passée dans un pipe.

Un pipe (|) envoie la sortie d’une commande vers l’entrée de la suivante :

Fenêtre de terminal
ls -l /etc | wc -l # nombre d'entrées dans /etc
ps aux | grep nginx | grep -v grep # processus nginx
cat journal.log | sort | uniq -c | sort -rn | head -5 # 5 lignes les plus fréquentes
du -sh /var/* 2>/dev/null | sort -h | tail -5 # 5 plus gros dossiers
Fenêtre de terminal
./script.sh | tee sortie.log # affiche à l'écran et écrit dans sortie.log
./script.sh | tee -a sortie.log # ajoute au fichier au lieu de l'écraser
echo "ligne" | sudo tee /etc/fichier # écrire dans un fichier protégé
echo "ligne" | sudo tee -a /etc/fichier # idem, en ajoutant

sudo echo "x" > /etc/fichier ne fonctionne pas : la redirection est exécutée par le shell de l’utilisateur, pas par sudo. Utiliser tee.

Fournir plusieurs lignes à une commande :

Fenêtre de terminal
cat > configuration.conf <<EOF
serveur=$HOSTNAME
dossier=/var/www
EOF

Avec <<'EOF' (guillemets simples), les variables ne sont pas remplacées :

Fenêtre de terminal
cat <<'EOF'
Le texte reste littéral : $HOME
EOF

Texte envoyé à une commande depuis une variable (here-string) :

Fenêtre de terminal
grep "erreur" <<< "$contenu"

xargs transforme des lignes reçues en arguments d’une commande :

Fenêtre de terminal
find . -name "*.tmp" | xargs rm -f # fragile avec des espaces dans les noms
find . -name "*.tmp" -print0 | xargs -0 rm -f # robuste (séparateur nul)
find . -name "*.log" -print0 | xargs -0 -n 1 gzip # un fichier à la fois
cat serveurs.txt | xargs -I{} ping -c 1 {} # {} : valeur remplacée

Utiliser la sortie d’une commande comme si c’était un fichier :

Fenêtre de terminal
diff <(ls dossier1) <(ls dossier2) # compare deux listings
while read -r ligne; do echo "$ligne"; done < <(commande)

La seconde forme évite le piège de commande | while read ... : dans un pipe, la boucle s’exécute dans un sous-processus et les variables qu’elle modifie sont perdues.