Difference between revisions of "HelloBash Ep2"

From Tmplab
(Redirection vers un fichier sans écraser le contenu existant : >|)
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
'''contenu en cours de rédaction'''
 
  
 
= Un peu de théorie =
 
= Un peu de théorie =
Line 18: Line 16:
  
  
Un pts/stty est une simulation de tty, qui signifie teletype, un descendant du télégraphe, qui communiquait par modem et ligne télégraphique avec d'autres teletypes.
+
Un pts/stty est une «simulation de tty». TTY signifie TeleTYpe, qui est un descendant du télégraphe en usage dès les années 50.
[https://www.linusakesson.net/programming/tty/ Ici une analyse poussée, de ce qu'est un tty et les teletype].
+
 
 +
'''Il est amusant de savoir que les teletypes communiquaient par modem via un réseau dédié, nommé teletype network, qui a donné le nom <code>telnet</code>, un protocole défini dès la [https://tools.ietf.org/html/rfc15 RFC 15], dont vous trouverez une [https://write.as/365-rfcs/rfc-15 analyse récente ici].'''
 +
 
 +
Pour une analyse poussée des tty et des teletype [https://www.linusakesson.net/programming/tty/ voir ici].
  
 
'''Un tty est un programme dont la fonctionnalité première est de gèrer du flux de texte. '''
 
'''Un tty est un programme dont la fonctionnalité première est de gèrer du flux de texte. '''
Line 47: Line 48:
  
 
Dans les deux cas nous verrons des commandes utiles associées à ces manipulations
 
Dans les deux cas nous verrons des commandes utiles associées à ces manipulations
 
 
  
 
= Les redirections de flux =
 
= Les redirections de flux =
Line 81: Line 80:
 
Les deux opération suivantes auront des résultats différents  
 
Les deux opération suivantes auront des résultats différents  
  
  $ commande redirection_1 redirection_2
+
  commande redirection_1 redirection_2
  $ commande redirection_2 redirection_1
+
  commande redirection_2 redirection_1
  
 
=== Utilisation des flux standards pour les redirections===
 
=== Utilisation des flux standards pour les redirections===
Line 95: Line 94:
  
 
== Redirections de STDOUT et STDERR ==
 
== Redirections de STDOUT et STDERR ==
 +
  
 
=== Redirection simple : > et >> ===
 
=== Redirection simple : > et >> ===
Line 102: Line 102:
 
Un double >>  concatène la sortie vers une sortie existante ou créable
 
Un double >>  concatène la sortie vers une sortie existante ou créable
  
  $ ls > /tmp/list.txt
+
  ls > /tmp/list.txt
  $ ls >> /tmp/list.txt
+
  ls >> /tmp/list.txt
 +
 
 +
Pour ces redirections, le stream "1" est la valeur par défaut quand on indique pas la source. Les deux exemples précédents équivalent à
 +
 
 +
  ls 1>/tmp/list.txt
 +
  ls 1>>/tmp/list.txt
  
 
On peut décider de créer un fichier avec les syntaxes suivantes, qui ne prennent aucune entrée  
 
On peut décider de créer un fichier avec les syntaxes suivantes, qui ne prennent aucune entrée  
  
  $ : > /tmp/foo
+
  : > /tmp/foo
  $ > /tmp/foo
+
  > /tmp/foo
  
 +
=== Redirection vers un fichier sans écraser le contenu existant : |> ===
  
=== Redirections vers un fichier sans écraser le contenu existant : >| et >>| ===
 
  
Si on active la fonction <code>noclobber</code> de Bash, on ne peut modifier un fichier existant à moins d'utiliser cette syntaxe particulière
+
Si on active le mode <code>noclobber</code> de Bash, on ne peut modifier un fichier existant à moins d'utiliser cette syntaxe particulière
  $ echo "ok" > /tmp/test
+
  echo "ok" > /tmp/test
  $ set -o noclobber
+
  set -o noclobber
  $ echo "bad" > /tmp/test
+
  echo "bad" > /tmp/test
  $ echo "works" |> /tmp/test
+
  echo "works" |> /tmp/test
  
 
=== Redirection de STDERR : 2> ===
 
=== Redirection de STDERR : 2> ===
Line 123: Line 128:
 
'''Si on veut la sortie et les erreurs dans des fichiers différents'''
 
'''Si on veut la sortie et les erreurs dans des fichiers différents'''
  
  $ curl https://www.tmplab.org 1>/tmp/std 2>/tmp/err  
+
  curl https://www.tmplab.org 1>/tmp/std 2>/tmp/err  
  
 
'''Si on veut enregistrer à la fois les erreurs et la sortie dans un même fichier.'''
 
'''Si on veut enregistrer à la fois les erreurs et la sortie dans un même fichier.'''
  
  $  ls -lh /foo  > /tmp/out 2>&1
+
    ls -lh /foo  1>/tmp/out 2>&1
  $ cat /tmp/out
+
  cat /tmp/out
  
 
Attention, il faut bien rediriger d'abord la sortie sortie vers le fichier, sinon STDERR reste sur STDOUT
 
Attention, il faut bien rediriger d'abord la sortie sortie vers le fichier, sinon STDERR reste sur STDOUT
  
  $  ls -lh /foo  > /tmp/out 2>&1
+
    ls -lh /foo  2>&1 1>/tmp/out  
 
   ls: impossible d'accéder à '/foo': Aucun fichier ou dossier de ce type
 
   ls: impossible d'accéder à '/foo': Aucun fichier ou dossier de ce type
  
Line 139: Line 144:
 
On utilise cette syntaxe pour rediriger 1 et 2 vers un descripteur de fichier commun
 
On utilise cette syntaxe pour rediriger 1 et 2 vers un descripteur de fichier commun
  
  $ ls -lh /proc/self/fd &>/tmp/out
+
  ls -lh /proc/self/fd &>/tmp/out
  $ cat /tmp/out
+
  cat /tmp/out
  
 
On voit que 1 et 2 sont bien pointées vers /dev/null
 
On voit que 1 et 2 sont bien pointées vers /dev/null
Line 148: Line 153:
 
On peut rediriger une sortie vers un flux numéroté comme STDERR.
 
On peut rediriger une sortie vers un flux numéroté comme STDERR.
  
  $ echo "Ooops" 1>/dev/null >&2
+
  echo "Ooops" 1>&2
  
 
== Redirections de STDIN ==
 
== Redirections de STDIN ==
Line 156: Line 161:
 
Cette syntaxe redirige par défaut le flux numéroté "0" vers le fichier indiqué
 
Cette syntaxe redirige par défaut le flux numéroté "0" vers le fichier indiqué
  
  $ ls /proc/self/fd -lh </tmp/out
+
  ls /proc/self/fd -lh </tmp/out
  
 
Elle peut être utile pour lancer une série de commandes SQL :
 
Elle peut être utile pour lancer une série de commandes SQL :
  
  $ echo "show databases" > /tmp/query.sql
+
  echo "show databases" > /tmp/query.sql
  $ mysql < /tmp/query.sql
+
  mysql < /tmp/query.sql
  
  
Line 170: Line 175:
 
L'entrée est démarquée par la suite de caractères qui suit les caractères "<<". Elle se termine quand la suite de caractères est répétée sur une seule ligne avant un retour à la ligne, sans espaces.
 
L'entrée est démarquée par la suite de caractères qui suit les caractères "<<". Elle se termine quand la suite de caractères est répétée sur une seule ligne avant un retour à la ligne, sans espaces.
  
  $ cat << HEREDOC
+
  cat << HEREDOC
 
   hello Bash
 
   hello Bash
 
   It's great.
 
   It's great.
Line 178: Line 183:
 
On peut créer des fichiers complexes en associant à un HEREDOC
 
On peut créer des fichiers complexes en associant à un HEREDOC
  
  $ cat 1>/tmp/out << SOMETHING
+
  cat 1>/tmp/out << SOMETHING
 
   my file
 
   my file
 
   is  
 
   is  
Line 186: Line 191:
 
===  Redirection par une chaîne (Here Strings) : <<< ===  
 
===  Redirection par une chaîne (Here Strings) : <<< ===  
  
Un
+
Déclare une chaîne de caractères qui sera utilisé comme STDIN de la commande.
  
  $ cat <<< "Hello Bash"
+
  cat <<< "Hello Bash"
  $ bash <<< "sleep 1"
+
  bash <<< "sleep 1"
  
 
== Création et fermeture de flux ==
 
== Création et fermeture de flux ==
  
=== Fermeture d'un flux : N>&-  ===
 
  
Cette commande supprime le flux numéroté "N" qu'on place avant le ">&-" : il disparaît de la liste des descripteurs de fichiers du processus.
+
=== Création de nouveaux flux : N< et N> ===
 +
 
 +
Cette syntaxe génère un flux numéroté "N" qui sera selon le sens du chevron un flux en entrée ou sortie.
 +
 
 +
En utilisant la commande <code>exec</code> qui permet d'effectuer des redirections au sein du processus courant.
  
  $ bash -c "echo $$; exec 2>&-; sleep 60;"
+
  exec 3>/tmp/out
  $ ls -lh /proc/PID/fd # PID = le numéro du processus retourné par la commande ci-dessus
+
  exec 4</etc/passwd
 
+
  ls /proc/self/fd -lh
 +
  echo "test" >&3
 +
  cat /tmp/out
 +
  read -n 32 CONTENT <&4
 +
  echo $CONTENT
  
=== Création de nouveaux flux : N< ===
+
=== Fermeture d'un flux : N>&- N<&- ===
  
Cette syntaxe génère un flux numéroté "N".
+
Cette commande supprime le flux numéroté "N" qu'on place avant le ">&-" ou "<&-".
  
Ici, on créé un flux "5" en copiant la cible de 2, qui lui-même change deux fois de directions.
+
Ce flux disparaît de la liste des descripteurs de fichiers du processus.
  
  $ ls -lh /proc/self/fd 2>/tmp/out 5<&2 2>/dev/null
+
  ls /proc/self/fd -lh
 +
  exec 3<&-
 +
  exec 4>&-
 +
  ls /proc/self/fd -lh
  
  
Line 214: Line 229:
 
Cette syntaxe permet de définir un flux numéroté N qui peut être utilisé à la fois pour lire et pour écrire.
 
Cette syntaxe permet de définir un flux numéroté N qui peut être utilisé à la fois pour lire et pour écrire.
  
  $ echo 1234567890 > /tmp/file
+
  echo 1234567890 > /tmp/file
  $ exec 3<> /tmp/file
+
  exec 3<> /tmp/file
  $ read -n 4 <&3
+
  read -n 4 <&3
  $ echo -n . >&3
+
  echo -n . >&3
  $ exec 3>&-
+
  exec 3>&-
  $ cat /tmp/file
+
  cat /tmp/file
  
 
Par exemple on peut appeler un flux TCP :
 
Par exemple on peut appeler un flux TCP :
  
  $ exec 3<>/dev/tcp/neverssl.com/80
+
  exec 3<>/dev/tcp/neverssl.com/80
  $ echo -e "GET / HTTP/1.1\r\nhost: neverssl.com\r\nConnection: close\r\n\r\n" >&3
+
  echo -e "GET / HTTP/1.1\r\nhost: neverssl.com\r\nConnection: close\r\n\r\n" >&3
  $ cat <&3
+
  cat <&3
  
 
=== Ouverture d'un flux "anonyme" : <( command ) ===
 
=== Ouverture d'un flux "anonyme" : <( command ) ===
Line 233: Line 248:
 
Par exemple, elle évite pour la commande suivante de stocker les résultats des commandes dans deux fichiers avant de les comparer.  
 
Par exemple, elle évite pour la commande suivante de stocker les résultats des commandes dans deux fichiers avant de les comparer.  
 
   
 
   
  $ diff -y <(man chattr) <(man chmod)  
+
  diff -y <(man chattr) <(man chmod)  
  
 
= Les Pipes =
 
= Les Pipes =
Line 241: Line 256:
 
Cette syntaxe permet de transmettre la STDOUT d'une commande comme STDIN d'une autre commande.  
 
Cette syntaxe permet de transmettre la STDOUT d'une commande comme STDIN d'une autre commande.  
  
  $ echo "hello" | ls  -lh /proc/self/fd
+
  echo "hello" | ls  -lh /proc/self/fd
  
 
On voit que le fd "0" est devenu un "pipe" : les données sont "versées" par la première commande dans la seconde.  
 
On voit que le fd "0" est devenu un "pipe" : les données sont "versées" par la première commande dans la seconde.  
Line 247: Line 262:
 
Exemple. La première commande liste des fichiers. Cette liste est transmise à grep qui ne sélectionne que les lignes contenant un mot particulier
 
Exemple. La première commande liste des fichiers. Cette liste est transmise à grep qui ne sélectionne que les lignes contenant un mot particulier
  
  $ ls -lh /etc | grep shadow
+
  ls -lh /etc | grep shadow
  
 
Cette syntaxe toute simple ouvre beaucoup de possibilités. Quelques exemples.
 
Cette syntaxe toute simple ouvre beaucoup de possibilités. Quelques exemples.
  
  $ ls -lh /etc | wc
+
  ls -lh /etc | wc
  $ ls -lh /etc | head
+
  ls -lh /etc | head
  $ ls -lh /etc | tail
+
  ls -lh /etc | tail
  $ ls -lh /etc | tr "aeiou" "_"
+
  ls -lh /etc | tr "aeiou" "_"
  $ ls -lh /etc |fmt -g 20  -s -
+
  ls -lh /etc |fmt -g 20  -s -
  
 
Les commandes comme <code>fmt</code> acceptent souvent le caractère "-" pour signaler que les données à traiter sont fournies en input
 
Les commandes comme <code>fmt</code> acceptent souvent le caractère "-" pour signaler que les données à traiter sont fournies en input
Line 261: Line 276:
 
On peut se retrouver à enchaîner les pipes.
 
On peut se retrouver à enchaîner les pipes.
  
  $ cat *.txt | sort | uniq > result-file
+
  cat *.txt | sort | uniq > result-file
  
 
=== Le pipe de redirection multi sorties :  |& ===
 
=== Le pipe de redirection multi sorties :  |& ===
  
  $ ls /foo |& cat >/tmp/out
+
Cette redirection renvoie à la fois STDOUT et STDERR dans le pipe
 +
 
 +
  ls /foo |& cat >/tmp/out
  
== Autre commandes ==
+
= Autre commandes =
  
 
=== tee ===
 
=== tee ===
Line 273: Line 290:
 
Afficher sur l'écran la sortie standard et l'envoyer dans un fichier simultanément
 
Afficher sur l'écran la sortie standard et l'envoyer dans un fichier simultanément
  
  $ cmd |   file
+
  echo "Do you want some tee?" | tee /tmp/out
 +
  cat /tmp/out
  
 
=== Descripteurs de fichiers nommés  ===
 
=== Descripteurs de fichiers nommés  ===
  
Open a file for writing using a named file descriptor called {filew} (bash 4.1+).
+
Ouvre un flux selon un nom de variable fourni.
Ouvre un flux selon un nom de variable fourni. Le contenu de la variable est le numéro du flux.
+
 
 +
Le contenu de la variable est le numéro du flux.
 +
 
 +
  exec {myfd}> /tmp/out
 +
  echo $myfd
 +
  ls  -lh /proc/self/fd
 +
  echo "Noice" >&$myfd
 +
  cat /tmp/out
 +
 
 +
 
 +
=== Envoyer toute la sortie vers un fichier tout en l'affichant ===
  
  $ exec {myfd}> /tmp/out
+
Placée au début d'un programme cette ligne permet d'afficher la sortie des commandes tout en l'envoyant également vers un fichier
  $ echo $myfd
 
  $ ls  -lh /proc/self/fd
 
  $ echo "Noice" >&$myfd
 
  $ cat /tmp/out
 
  
 +
  #!/bin/bash
 +
  exec &> >(tee -a "$LOG_FILE")
 +
  echo  "This is 1"
 +
  echo "This is 2" >&2
  
 
=== Intervertir STDERR et STDOUT ===
 
=== Intervertir STDERR et STDOUT ===
Line 291: Line 319:
 
Cette ligne stocke STDOUT dans un flux numéroté "3", puis copie la cible de STDERR vers flux "1", avant de recopier STDIN vers le flux "2"  
 
Cette ligne stocke STDOUT dans un flux numéroté "3", puis copie la cible de STDERR vers flux "1", avant de recopier STDIN vers le flux "2"  
  
  $ echo "hello bash" 3>&1 1>&2 2>&3  
+
  echo "hello bash" 3>&1 1>&2 2>&3  
  $ curl -v https://www.tmplab.org 1>/tmp/out 2>/tmp/err 3>&1 1>&2 2>&3
+
  curl -v https://www.tmplab.org 1>/tmp/out 2>/tmp/err 3>&1 1>&2 2>&3
  
 
=== Récupérer les codes de sortie de commandes enchaînées avec des pipes  ===
 
=== Récupérer les codes de sortie de commandes enchaînées avec des pipes  ===
  
  $ cmd1 | cmd2 | cmd3 | cmd4
+
  cmd1 | cmd2 | cmd3 | cmd4
  $ echo ${PIPESTATUS[@]}  
+
  echo ${PIPESTATUS[@]}
  
 
= Sources =
 
= Sources =
https://catonmat.net/bash-one-liners-explained-part-three
+
 
https://catonmat.net/ftp/bash-redirections-cheat-sheet.pdf
+
* https://catonmat.net/bash-one-liners-explained-part-three
https://xavcc.frama.io/introduction-stream/
+
* https://catonmat.net/ftp/bash-redirections-cheat-sheet.pdf
https://developer.ibm.com/tutorials/l-lpic1-103-2/
+
* https://xavcc.frama.io/introduction-stream/
https://developer.ibm.com/tutorials/l-lpic1-103-4/
+
* https://developer.ibm.com/tutorials/l-lpic1-103-2/
https://www.gnu.org/software/bash/manual/html_node/Redirections.html
+
* https://developer.ibm.com/tutorials/l-lpic1-103-4/
https://www.tldp.org/LDP/abs/html/io-redirection.html
+
* https://www.gnu.org/software/bash/manual/html_node/Redirections.html
https://brennan.io/2015/01/16/write-a-shell-in-c/
+
* https://www.tldp.org/LDP/abs/html/io-redirection.html
 +
* https://brennan.io/2015/01/16/write-a-shell-in-c/

Latest revision as of 23:02, 26 March 2020

Un peu de théorie

Le shell que vous utilisez est probablement un stty

Un teletype
 $ tty
 /dev/pts/0
 $ whatis pts
 pts (4)              - pseudoterminal master and slave
 $ stty
 speed 38400 baud; line = 0;
 -brkint -imaxbel


Un pts/stty est une «simulation de tty». TTY signifie TeleTYpe, qui est un descendant du télégraphe en usage dès les années 50.

Il est amusant de savoir que les teletypes communiquaient par modem via un réseau dédié, nommé teletype network, qui a donné le nom telnet, un protocole défini dès la RFC 15, dont vous trouverez une analyse récente ici.

Pour une analyse poussée des tty et des teletype voir ici.

Un tty est un programme dont la fonctionnalité première est de gèrer du flux de texte.

Voilà ce que fait -un peu caricaturalement- un terminal comme à l'époque du teletype :

  1. Recevoir un text (input/STDIN) : création d'une chaîne de caractères individuels
  2. Analyser le texte saisi (parsing) : découpe de la chaîne de texte en commande + arguments
  3. Exécuter la commande avec ses arguments (exec[vlpe]) et retransmission des chaînes de sortie standard (output/STDOUT) et d'erreurs (errors/STDERR)


Ce qu'on appelle flux (ou streams) ce sont les différentes chaînes de caractères en transit : les STDIN, STDOUT, STDERR

Bash permet de manipuler ces flux. Force du shell : combiner des commandes existantes entre elles, via les flux.

Métaphore: un teletype qui enverrait un message en Italie, récupèrerait la sortie, remplacerait certains mots et retransmettrait le résultat en Allemagne.

Dans le cas d'un stty, pas besoin d'édition papier, tout se fait avec des chaînes de texte.

Les types de manipulation

Nous allons voir les manipulations de flux suivantes

  1. les redirections
  2. les pipes (pipelines/tubes)


Dans les deux cas nous verrons des commandes utiles associées à ces manipulations

Les redirections de flux

STDIN, STDOUT, STDERR

Un terminal est instancié avec 3 flux natifs numérotés 0, 1, et 2

 $ ls -go /proc/self/fd
 total 0
 lrwx------ 1 <...> 0 -> /dev/pts/4
 lrwx------ 1 <...> 1 -> /dev/pts/4
 lrwx------ 1 <...> 2 -> /dev/pts/4
 lr-x------ 1 <...> 3 -> /proc/6017/fd
 $ ls -go /dev/STDIN
 lrwxrwxrwx 1 <...> /dev/STDIN -> /proc/self/fd/0

Ce sont des descripteurs de fichiers (file descriptors/fd) et ils peuvent être manipulés en les substituant avec d'autres descripteurs de fichiers.

Ils ont chacun un numéro standardisé :

  • 0 == STDIN
  • 1 == STDOUT
  • 2 == STDERR


La redirection permet aux descripteurs de fichier des commandes d'être dupliqués, ouverts, fermés, de se référer à différents fichiers et de modifier les fichiers lus et écrits par la commande.

Les opérateurs de redirection peuvent précéder ou apparaître n'importe où dans une commande simple ou peuvent suivre une commande. Les redirections sont traitées dans l'ordre dans lequel elles apparaissent, de gauche à droite.

Les deux opération suivantes auront des résultats différents

  commande redirection_1 redirection_2
  commande redirection_2 redirection_1

Utilisation des flux standards pour les redirections

Les numéros de flux (0,1,2) sont utilisés pour rediriger les flux par défaut

Par défault, les opérateurs qui manipulent les flux input utilisent le numéro de fd 0 (STDIN).

Par défault, les opérateurs qui manipulent les flux output utilisent le numéro de fd 1 (STDOUT)

Pour signifier qu'on veut rediriger vers un flux existant, on le préfixe avec un "&", sinon Bash pense que vous parlez du fichier nommé "1", pas de /proc/self/fd/1.

Redirections de STDOUT et STDERR

Redirection simple : > et >>

Un simple > remplace un contenu existant vers une sortie existante ou créable

Un double >> concatène la sortie vers une sortie existante ou créable

  ls > /tmp/list.txt
  ls >> /tmp/list.txt

Pour ces redirections, le stream "1" est la valeur par défaut quand on indique pas la source. Les deux exemples précédents équivalent à

  ls 1>/tmp/list.txt
  ls 1>>/tmp/list.txt

On peut décider de créer un fichier avec les syntaxes suivantes, qui ne prennent aucune entrée

  : > /tmp/foo
  > /tmp/foo

Redirection vers un fichier sans écraser le contenu existant : |>

Si on active le mode noclobber de Bash, on ne peut modifier un fichier existant à moins d'utiliser cette syntaxe particulière

  echo "ok" > /tmp/test
  set -o noclobber
  echo "bad" > /tmp/test
  echo "works" |> /tmp/test

Redirection de STDERR : 2>

Si on veut la sortie et les erreurs dans des fichiers différents

  curl https://www.tmplab.org 1>/tmp/std 2>/tmp/err 

Si on veut enregistrer à la fois les erreurs et la sortie dans un même fichier.

   ls -lh /foo  1>/tmp/out 2>&1
  cat /tmp/out

Attention, il faut bien rediriger d'abord la sortie sortie vers le fichier, sinon STDERR reste sur STDOUT

   ls -lh /foo  2>&1 1>/tmp/out 
 ls: impossible d'accéder à '/foo': Aucun fichier ou dossier de ce type

Redirection de STDERR et STDOUT : &>

On utilise cette syntaxe pour rediriger 1 et 2 vers un descripteur de fichier commun

  ls -lh /proc/self/fd &>/tmp/out
  cat /tmp/out

On voit que 1 et 2 sont bien pointées vers /dev/null

Envoi de caractères dans STDERR : >&2

On peut rediriger une sortie vers un flux numéroté comme STDERR.

  echo "Ooops" 1>&2

Redirections de STDIN

Redirection par un contenu de fichier : <

Cette syntaxe redirige par défaut le flux numéroté "0" vers le fichier indiqué

  ls /proc/self/fd -lh </tmp/out

Elle peut être utile pour lancer une série de commandes SQL :

  echo "show databases" > /tmp/query.sql
  mysql < /tmp/query.sql


Redirection par un document (Here Documents) : <<

Un Here Documents crée une entrée multiligne qui est passée en STDIN à la commande.

L'entrée est démarquée par la suite de caractères qui suit les caractères "<<". Elle se termine quand la suite de caractères est répétée sur une seule ligne avant un retour à la ligne, sans espaces.

  cat << HEREDOC
 hello Bash
 It's great.
 We love it!
 HEREDOC

On peut créer des fichiers complexes en associant à un HEREDOC

  cat 1>/tmp/out << SOMETHING
 my file
 is 
 multiline!
 SOMETHING 

Redirection par une chaîne (Here Strings) : <<<

Déclare une chaîne de caractères qui sera utilisé comme STDIN de la commande.

  cat <<< "Hello Bash"
  bash <<< "sleep 1"

Création et fermeture de flux

Création de nouveaux flux : N< et N>

Cette syntaxe génère un flux numéroté "N" qui sera selon le sens du chevron un flux en entrée ou sortie.

En utilisant la commande exec qui permet d'effectuer des redirections au sein du processus courant.

  exec 3>/tmp/out
  exec 4</etc/passwd
  ls /proc/self/fd -lh
  echo "test" >&3
  cat /tmp/out
  read -n 32 CONTENT <&4
  echo $CONTENT

Fermeture d'un flux : N>&- N<&-

Cette commande supprime le flux numéroté "N" qu'on place avant le ">&-" ou "<&-".

Ce flux disparaît de la liste des descripteurs de fichiers du processus.

  ls /proc/self/fd -lh
  exec 3<&-
  exec 4>&-
  ls /proc/self/fd -lh


Ouverture d'un flux pour entrée et sortie : N<>

Cette syntaxe permet de définir un flux numéroté N qui peut être utilisé à la fois pour lire et pour écrire.

  echo 1234567890 > /tmp/file
  exec 3<> /tmp/file
  read -n 4 <&3
  echo -n . >&3
  exec 3>&-
  cat /tmp/file

Par exemple on peut appeler un flux TCP :

  exec 3<>/dev/tcp/neverssl.com/80
  echo -e "GET / HTTP/1.1\r\nhost: neverssl.com\r\nConnection: close\r\n\r\n" >&3
  cat <&3

Ouverture d'un flux "anonyme" : <( command )

Cette syntaxe crée un type de descripteur de fichier particulier (un FIFO) qui contient le résultat de la commande appelée.

Par exemple, elle évite pour la commande suivante de stocker les résultats des commandes dans deux fichiers avant de les comparer.

  diff -y <(man chattr) <(man chmod) 

Les Pipes

Le pipe simple : |

Cette syntaxe permet de transmettre la STDOUT d'une commande comme STDIN d'une autre commande.

  echo "hello" | ls  -lh /proc/self/fd

On voit que le fd "0" est devenu un "pipe" : les données sont "versées" par la première commande dans la seconde.

Exemple. La première commande liste des fichiers. Cette liste est transmise à grep qui ne sélectionne que les lignes contenant un mot particulier

  ls -lh /etc | grep shadow

Cette syntaxe toute simple ouvre beaucoup de possibilités. Quelques exemples.

  ls -lh /etc | wc
  ls -lh /etc | head
  ls -lh /etc | tail
  ls -lh /etc | tr "aeiou" "_"
  ls -lh /etc |fmt -g 20  -s -

Les commandes comme fmt acceptent souvent le caractère "-" pour signaler que les données à traiter sont fournies en input

On peut se retrouver à enchaîner les pipes.

  cat *.txt | sort | uniq > result-file

Le pipe de redirection multi sorties : |&

Cette redirection renvoie à la fois STDOUT et STDERR dans le pipe

  ls /foo |& cat >/tmp/out

Autre commandes

tee

Afficher sur l'écran la sortie standard et l'envoyer dans un fichier simultanément

  echo "Do you want some tee?" |  tee /tmp/out
  cat /tmp/out 

Descripteurs de fichiers nommés

Ouvre un flux selon un nom de variable fourni.

Le contenu de la variable est le numéro du flux.

  exec {myfd}> /tmp/out
  echo $myfd
  ls  -lh /proc/self/fd
  echo "Noice" >&$myfd
  cat /tmp/out


Envoyer toute la sortie vers un fichier tout en l'affichant

Placée au début d'un programme cette ligne permet d'afficher la sortie des commandes tout en l'envoyant également vers un fichier

 #!/bin/bash 
 exec &> >(tee -a "$LOG_FILE")
 echo  "This is 1"
 echo "This is 2" >&2

Intervertir STDERR et STDOUT

Cette ligne stocke STDOUT dans un flux numéroté "3", puis copie la cible de STDERR vers flux "1", avant de recopier STDIN vers le flux "2"

  echo "hello bash" 3>&1 1>&2 2>&3 
  curl -v https://www.tmplab.org 1>/tmp/out 2>/tmp/err 3>&1 1>&2 2>&3

Récupérer les codes de sortie de commandes enchaînées avec des pipes

  cmd1 | cmd2 | cmd3 | cmd4
  echo ${PIPESTATUS[@]}

Sources