$ carnet-linux
PHASE 2 · MODULE 05

Redirections, pipes & filtres

Le cœur de la philosophie Unix : des petits outils qui font une chose, et des tuyaux pour les assembler. À la fin de ce module, tu analyseras un journal de serveur web en une seule ligne de commande.

⏱️ Lecture ~55 min 🧪 Pratique ~1 h 30 🎚️ Niveau intermédiaire
Tux

🎯 Ce que tu sauras à la fin

🚰

Les flux

stdin, stdout, stderr et leurs numéros.

↪️

Rediriger

>, >>, 2>, /dev/null…

🔗

Combiner

Construire des pipelines avec |.

🧰

Filtrer

grep, sort, uniq, cut, sed, awk.

Les trois flux standard

▶ Vidéo · 1 min 30Les trois flux et les redirections0, 1, 2 et les chevrons
Animation réalisée pour ce cours. Voix off et musique générées par IA (Google Gemini et Lyria).

Tout programme démarre avec trois canaux ouverts, numérotés :

programme ex. ls ⌨️ clavier 0 · stdin 1 · stdout 2 · stderr 🖥️ écran 🖥️ écran
Par défaut, stdin vient du clavier, stdout et stderr vont à l'écran. Mais ce sont deux canaux distincts.
N°NomRôlePar défaut
0stdinEntrée standard : ce que le programme litLe clavier
1stdoutSortie standard : les résultatsL'écran
2stderrSortie d'erreur : les messages d'erreurL'écran

Les redirections

SyntaxeEffet
cmd > fichierstdout dans un fichier, écrasé s'il existe
cmd >> fichierstdout ajouté à la fin du fichier
cmd 2> erreurs.txtstderr dans un fichier
cmd > tout.txt 2>&1stdout dans le fichier, puis stderr envoyé au même endroit que stdout
cmd &> tout.txtRaccourci Bash pour la ligne précédente
cmd < fichierstdin lu depuis un fichier
cmd 2> /dev/nullFaire disparaître les erreurs dans le « trou noir »
user@ubuntu:~$ ls /etc /nexistepas > sortie.txt
ls: impossible d'accéder à '/nexistepas': Aucun fichier ou dossier de ce nom   # stderr reste à l'écran
user@ubuntu:~$ ls /etc /nexistepas > sortie.txt 2> erreurs.txt   # chacun dans son fichier
user@ubuntu:~$ find / -name "*.conf" 2> /dev/null     # sans les centaines de « Permission non accordée »
user@ubuntu:~$ echo "$(date) : sauvegarde OK" >> journal.txt   # tenir un journal
user@ubuntu:~$ wc -l < /etc/passwd                       # wc lit stdin : pas de nom de fichier affiché
37
> écrase sans prévenir

sort notes.txt > notes.txt vide le fichier : le shell le tronque avant même que sort ne le lise. On écrit toujours dans un autre fichier, puis on renomme. Pour se protéger, set -o noclobber fait refuser à Bash l'écrasement avec >.

L'ordre compte : 2>&1

2>&1 signifie « envoie stderr là où va stdout en ce moment ». Dans cmd > f 2>&1, stdout va déjà dans f : tout y va. Dans cmd 2>&1 > f, stderr a été branché sur l'écran avant que stdout ne soit redirigé : les erreurs restent à l'écran.

Écrire plusieurs lignes : le « here-document »

user@ubuntu:~$ cat > courses.txt << 'FIN'
> pommes
> pain
> café
> FIN
user@ubuntu:~$ cat courses.txt
pommes
pain
café

Tout ce qui est tapé jusqu'au mot FIN (seul sur sa ligne) est envoyé sur stdin. Très utilisé dans les scripts pour créer des fichiers de configuration.

Le pipe : l'art de combiner

▶ Vidéo · 1 min 30Le pipe : l'art de combinerun vrai problème résolu en une ligne
Animation réalisée pour ce cours. Voix off et musique générées par IA (Google Gemini et Lyria).

Le pipe | (AltGr + 6 sur un clavier AZERTY) branche le stdout d'une commande sur le stdin de la suivante. Les données coulent d'un programme à l'autre, sans fichier intermédiaire, et tous les programmes tournent en même temps.

📜
cat acces.logtoutes les lignes
|
✂️
cut -d' ' -f1garde l'adresse IP
|
🔤
sortregroupe les identiques
|
🔢
uniq -ccompte
|
🏆
sort -nr | headle top
Une idée de 1973

Le pipe a été proposé par Doug McIlroy aux Bell Labs et ajouté à Unix par Ken Thompson en 1973, en une nuit selon la légende. McIlroy a résumé la philosophie qui en découle : « Écrivez des programmes qui font une seule chose et la font bien. Écrivez des programmes qui travaillent ensemble. Écrivez des programmes qui manipulent des flux de texte. »

Préparer un fichier d'exemple pour tout le module

Pour s'entraîner, voici un petit journal de serveur web. Copie ce bloc dans ton terminal : il crée ~/labo/acces.log.

user@ubuntu:~$ mkdir -p ~/labo && cat > ~/labo/acces.log << 'FIN'
192.168.1.10 - - [23/Oct/2026:10:01:12] "GET /index.html" 200 5120
192.168.1.22 - - [23/Oct/2026:10:01:15] "GET /contact.html" 200 2048
10.0.0.5 - - [23/Oct/2026:10:02:01] "GET /admin" 403 512
192.168.1.10 - - [23/Oct/2026:10:02:30] "GET /images/logo.png" 200 15360
192.168.1.10 - - [23/Oct/2026:10:03:12] "GET /blog.html" 200 8192
10.0.0.5 - - [23/Oct/2026:10:03:45] "GET /admin" 403 512
172.16.0.8 - - [23/Oct/2026:10:04:02] "GET /index.html" 200 5120
192.168.1.22 - - [23/Oct/2026:10:04:59] "GET /page-perdue.html" 404 256
10.0.0.5 - - [23/Oct/2026:10:05:30] "POST /login" 401 128
192.168.1.10 - - [23/Oct/2026:10:06:10] "GET /index.html" 200 5120
172.16.0.8 - - [23/Oct/2026:10:06:44] "GET /blog.html" 200 8192
10.0.0.5 - - [23/Oct/2026:10:07:02] "POST /login" 401 128
FIN
user@ubuntu:~/labo$ cut -d' ' -f1 acces.log | sort | uniq -c | sort -nr | head -3
      4 192.168.1.10
      4 10.0.0.5
      2 192.168.1.22
Construire un pipeline pas à pas

Ne tape jamais un long pipeline d'un coup. Ajoute une commande à la fois, regarde le résultat, puis rappelle la ligne avec ↑ et ajoute le maillon suivant. C'est comme ça que les pros procèdent.

La boîte à filtres

grep : garder les lignes qui correspondent

OptionEffetExemple
Lignes contenant le motifgrep 404 acces.log
-iIgnorer majuscules/minusculesgrep -i error /var/log/syslog
-vInverser : lignes qui ne correspondent pasgrep -v '^#' fichier.conf
-cCompter les lignesgrep -c 403 acces.log
-nAfficher les numéros de lignegrep -n root /etc/passwd
-rChercher dans tous les fichiers d'un dossiergrep -r "Port" /etc/ssh/
-wMot entier seulementgrep -w log fichier
-EExpressions régulières étenduesgrep -E '40[134]' acces.log

Les expressions régulières (^ début de ligne, $ fin, . n'importe quel caractère…) seront approfondies au module 06.

Trier, dédoublonner, compter, découper

CommandeRôleOptions clés
sortTrier les lignes-n numérique · -r inverse · -h tailles (2K, 1G) · -k2 sur la 2e colonne · -t: séparateur · -u sans doublons
uniqFusionner les lignes identiques consécutives-c compter · -d seulement les doublons. Toujours après sort !
wcCompter-l lignes · -w mots · -c octets
cutExtraire des colonnes-d: séparateur · -f1,3 champs · -c1-10 caractères
trRemplacer ou supprimer des caractèrestr a-z A-Z majuscules · tr -d '\r' supprimer · tr -s ' ' compresser
head / tailGarder le début / la fin-n 5
teeÉcrire dans un fichier et laisser passer-a ajouter. Ex. cmd | tee resultat.txt
user@ubuntu:~$ cut -d: -f1,7 /etc/passwd | head -3          # identifiant et shell
root:/bin/bash
daemon:/usr/sbin/nologin
bin:/usr/sbin/nologin
user@ubuntu:~$ cut -d: -f7 /etc/passwd | sort | uniq -c     # combien de comptes par shell ?
      1 /bin/false
      2 /bin/bash
      1 /bin/sync
     33 /usr/sbin/nologin
user@ubuntu:~$ du -sh /var/* 2>/dev/null | sort -hr | head -3   # les plus gros dossiers de /var
2,1G	/var/lib
410M	/var/cache
95M	/var/log
user@ubuntu:~$ echo "bonjour linux" | tr a-z A-Z
BONJOUR LINUX

Aperçu de sed et awk

Deux outils plus puissants, presque des langages à eux seuls. L'essentiel suffit pour 90 % des usages.

sed : rechercher et remplacer dans un flux

user@ubuntu:~/labo$ sed 's/GET/LECTURE/' acces.log | head -2       # s/ancien/nouveau/ : 1re occurrence par ligne
192.168.1.10 - - [23/Oct/2026:10:01:12] "LECTURE /index.html" 200 5120
192.168.1.22 - - [23/Oct/2026:10:01:15] "LECTURE /contact.html" 200 2048
user@ubuntu:~/labo$ sed 's/a/A/g' courses.txt                 # g : toutes les occurrences
user@ubuntu:~/labo$ sed -n '3,5p' acces.log                   # afficher les lignes 3 à 5
user@ubuntu:~/labo$ sed '/403/d' acces.log                     # supprimer les lignes contenant 403
user@ubuntu:~/labo$ sed -i.bak 's/pain/baguette/' courses.txt   # -i : modifie le fichier (copie .bak)

awk : travailler par colonnes

awk découpe chaque ligne en champs $1, $2… (séparés par des espaces, ou par ce que précise -F) et permet des conditions et des calculs.

Dans notre journal, la méthode "GET forme un champ à elle seule : l'IP est $1, la page $6, le code HTTP $7 et la taille $8.

user@ubuntu:~/labo$ awk '{print $1, $7}' acces.log | head -2      # IP et code HTTP
192.168.1.10 200
192.168.1.22 200
user@ubuntu:~/labo$ awk '$7 >= 400' acces.log | wc -l          # nombre de requêtes en erreur
5
user@ubuntu:~/labo$ awk '{total += $8} END {print total " octets"}' acces.log
50688 octets
user@ubuntu:~$ awk -F: '$3 >= 1000 {print $1}' /etc/passwd       # les comptes humains
user
nobody

Enchaîner des commandes : ; && || et $( )

SyntaxeSignificationExemple
a ; bb s'exécute après a, quoi qu'il arrivecd /tmp ; ls
a && bb seulement si a a réussi (code 0)sudo apt update && sudo apt upgrade
a || bb seulement si a a échouéping -c1 serveur || echo "injoignable"
$(commande)Remplacé par la sortie de la commandeecho "Noyau : $(uname -r)"
user@ubuntu:~$ mkdir sauvegarde && cp -r labo sauvegarde/ && echo "OK" || echo "ÉCHEC"
OK
user@ubuntu:~$ cp labo/acces.log "acces-$(date +%F).log" && ls acces-*
acces-2026-10-23.log

Glossaire du module

stdin / stdout / stderr
Entrée standard (0), sortie standard (1), sortie d'erreur (2).
Redirection
Changer la destination ou la source d'un flux : >, >>, 2>, <.
/dev/null
Fichier spécial qui avale tout ce qu'on lui envoie.
Here-document
Bloc de texte envoyé sur stdin avec << MOT.
Pipe
| : relie le stdout d'une commande au stdin de la suivante.
Pipeline
Chaîne de commandes reliées par des pipes.
Filtre
Programme qui lit stdin, transforme, et écrit sur stdout.
grep
Garde les lignes qui correspondent à un motif.
sed
Éditeur de flux : remplacements, suppressions de lignes.
awk
Traitement par colonnes, conditions et calculs.
&& / ||
Exécuter la suite si succès / si échec.
Substitution de commande
$(cmd) est remplacé par la sortie de cmd.

🧠 Quiz : as-tu tout retenu ?

1. Quel est le numéro de la sortie d'erreur ?
0 = stdin, 1 = stdout, 2 = stderr.
2. Quelle différence entre > et >> ?
> remplace le contenu, >> l'allonge.
3. Comment masquer uniquement les messages d'erreur d'une commande ?
> /dev/null masquerait au contraire les résultats et garderait les erreurs.
4. Pourquoi met-on sort avant uniq -c ?
Sans tri, deux lignes identiques séparées seraient comptées séparément.
5. Que fait grep -v '^#' fichier.conf ?
-v inverse la sélection ; ^# = « commence par # ». Le fichier n'est pas modifié.
6. Dans awk '{print $3}', que représente $3 ?
awk découpe chaque ligne en champs numérotés. Les apostrophes empêchent le shell d'interpréter $3.
7. sudo apt update && sudo apt upgrade : quand upgrade est-il lancé ?
&& enchaîne en cas de succès (code de retour 0).
8. Que contient notes.txt après sort notes.txt > notes.txt ?
Le shell ouvre (et vide) notes.txt pour la redirection avant que sort ne le lise.
Réponds aux questions pour voir ton score.

🚀 Mission pratique

À faire dans la machine virtuelle

Coche chaque étape une fois faite : sa correction s'affiche juste en dessous.

  • ✅ Correction
    $ wc -l ~/labo/acces.log
    12 /home/user/labo/acces.log

    Si le compte n'est pas bon, vérifie que FIN était bien seul sur sa dernière ligne.

  • ✅ Correction
    $ cd ~/labo
    $ ls /etc > liste.txt
    $ ls /var >> liste.txt
    $ wc -l liste.txt
    215 liste.txt
  • ✅ Correction
    $ ls /etc /nexistepas > ok.txt 2> ko.txt
    $ cat ko.txt
    ls: impossible d'accéder à '/nexistepas': Aucun fichier ou dossier de ce nom
    $ ls /etc /nexistepas > tout.txt 2>&1
    $ head -1 tout.txt
    ls: impossible d'accéder à '/nexistepas': Aucun fichier ou dossier de ce nom
  • ✅ Correction
    $ find /etc -name "*.conf" 2> /dev/null | wc -l
    118

    Le nombre exact varie. Sans 2> /dev/null, les dossiers interdits produisent des messages « Permission non accordée ».

  • ✅ Correction
    $ grep ' 403 ' acces.log
    10.0.0.5 - - [23/Oct/2026:10:02:01] "GET /admin" 403 512
    10.0.0.5 - - [23/Oct/2026:10:03:45] "GET /admin" 403 512
    $ grep -c ' 403 ' acces.log
    2

    Les espaces autour de 403 évitent de trouver ce nombre ailleurs dans la ligne (une taille, une heure).

  • ✅ Correction
    $ cut -d' ' -f1 acces.log | sort | uniq -c | sort -nr | head -3
          4 192.168.1.10
          4 10.0.0.5
          2 192.168.1.22

    Il y a deux égalités : 192.168.1.10 et 10.0.0.5 (4 requêtes chacune), puis 192.168.1.22 et 172.16.0.8 (2 chacune). L'ordre des ex æquo peut varier.

  • ✅ Correction
    $ awk '{print $6}' acces.log | sort -u
    /admin"
    /blog.html"
    /contact.html"
    /images/logo.png"
    /index.html"
    /login"
    /page-perdue.html"
    $ awk '{print $6}' acces.log | tr -d '"' | sort -u   # sans le guillemet
  • ✅ Correction
    $ awk '{total += $8} END {print total}' acces.log
    50688
    $ awk '$7 >= 400' acces.log | wc -l
    5
  • ✅ Correction
    $ sed 's/GET/LECTURE/' acces.log > acces-fr.log
    $ grep -c LECTURE acces-fr.log
    10
    $ grep -c GET acces.log
    10
  • ✅ Correction
    $ cut -d' ' -f1 acces.log | sort | uniq -c | sort -nr | tee "rapport-$(date +%F).txt" && echo "Rapport prêt"
          4 192.168.1.10
          4 10.0.0.5
          2 192.168.1.22
          1 ...
    Rapport prêt

💬 Questions fréquentes

Les questions qui reviennent le plus souvent sur ce module, avec leurs réponses.

Comment taper le caractère | sur un clavier AZERTY ?

AltGr + 6 (la touche du tiret). Sur un Mac : Alt + Maj + L. Pour les autres symboles utiles : ~ = AltGr + 2 puis Espace, { } = AltGr + 4 / +, [ ] = AltGr + 5 / °.

sudo echo "texte" > /etc/fichier donne « Permission non accordée »

La redirection > est faite par ton shell, sans droits root ; seul echo tourne avec sudo. La solution : echo "texte" | sudo tee /etc/fichier (ou sudo tee -a pour ajouter). Ici, c'est tee qui écrit, avec les droits de root.

Mon pipeline ne renvoie rien

Démonte-le : exécute la première commande seule, puis ajoute les maillons un par un avec ↑. Le coupable est souvent un séparateur mal choisi dans cut (espace contre tabulation) ou un grep sensible aux majuscules (essaie -i).