J'ai beaucoup de mal à comprendre comment utiliser les descripteurs de fichiers dans les scripts shell.
Je connais les bases telles que
exec 5 > /tmp/foo
Donc fd 5 est attaché à foo pour l'écriture.
exec 6 < /tmp/bar
… pour la lecture.
exec 5>&-
… fermer fd.
Maintenant, qu'est-ce que cela fait ?
#!/bin/bash
exec 5 > /tmp/foo
exec 6 < /tmp/bar
cat <&6 | while read a
do
echo $a >&5
done
Si je comprends bien &5
ferme le fd, alors comment la sortie est-elle toujours redirigée avec succès après chaque appel ?
Ceci est une copie des pâtes de :Ici
Il prétend l'utiliser sur un simple fichier echo $a > file
rendrait cela beaucoup plus rapide, mais je ne comprends pas. J'apprécierais tous les liens vers un tutoriel décent. J'ai l'impression que les pouvoirs de Google me font défaut.
Réponse acceptée :
Tout d'abord, notez que la syntaxe de fermeture est 5>&-
ou 6<&-
, selon que le descripteur de fichier est lu en écriture ou en lecture. Il semble y avoir une faute de frappe ou un problème de formatage dans cet article de blog.
Voici le script commenté.
exec 5>/tmp/foo # open /tmp/foo for writing, on fd 5
exec 6</tmp/bar # open /tmp/bar for reading, on fd 6
cat <&6 | # call cat, with its standard input connected to
# what is currently fd 6, i.e., /tmp/bar
while read a; do #
echo $a >&5 # write to fd 5, i.e., /tmp/foo
done #
Il n'y a pas de fermeture ici. Étant donné que toutes les entrées et sorties vont au même endroit dans cet exemple simple, l'utilisation de descripteurs de fichiers supplémentaires n'est pas nécessaire. Vous pourriez écrire
cat </tmp/bar |
while read a; do
echo $a
done >/tmp/foo
L'utilisation de descripteurs de fichiers explicites devient utile lorsque vous souhaitez écrire dans plusieurs fichiers à tour de rôle. Par exemple, considérez un script qui génère des données dans un fichier de sortie de données et enregistre les données dans un fichier journal et éventuellement des messages d'erreur également. Cela signifie trois canaux de sortie :un pour les données, un pour les journaux et un pour les erreurs. Puisqu'il n'y a que deux descripteurs standard pour la sortie, un troisième est nécessaire. Vous pouvez appeler exec
pour ouvrir les fichiers de sortie :
exec >data-file
exec 3>log-file
echo "first line of data"
echo "this is a log line" >&3
…
if something_bad_happens; then echo error message >&2; fi
exec >&- # close the data output file
echo "output file closed" >&3
La remarque sur l'efficacité intervient lorsque vous avez une redirection dans une boucle, comme celle-ci (en supposant que le fichier est vide pour commencer) :
while …; do echo $a >>/tmp/bar; done
A chaque itération, le programme ouvre /tmp/bar
, recherche la fin du fichier, ajoute des données et ferme le fichier. Il est plus efficace d'ouvrir le fichier une fois pour toutes :
while …; do echo $a; done >/tmp/bar
Lorsqu'il y a plusieurs redirections à des moments différents, appeler exec
effectuer des redirections plutôt que d'envelopper un bloc dans une redirection devient utile.
exec >/tmp/bar
while …; do echo $a; done
Vous trouverez plusieurs autres exemples de redirection en parcourant le io-redirection
tag sur ce site.