Sur OS X, comme sur tous les systèmes où ils sont pris en charge sauf Linux , l'ouverture /dev/fd/xest comme faire un dup(x), le fd résultant pointe plus ou moins vers la même description de fichier ouvert que sur fd x et en particulier aura le même décalage dans le fichier.
Linux est l'exception ici. Sous Linux, /dev/fd/xest un lien symbolique vers /proc/self/fd/xet /proc/self/fd/xest un pseudo-lien symbolique vers le fichier ouvert sur fd x. Sous Linux, lorsque vous effectuez une open("/dev/fd/x", somemode), vous obtenez une toute nouvelle description de fichier ouvert dans le même fichier que open on x. Le nouveau fd que vous obtenez n'est en aucun cas lié à fd x. En particulier, l'offset sera au début du fichier (sauf si vous l'ouvrez avec O_APPENDbien sûr) et le mode (lecture / écriture / ajout ...) peut être différent de celui sur fd x (vous pouvez même obtenir quelque chose de très différent de ce qui se trouve sur fd x, comme l'autre extrémité du tuyau lorsque vous l'ouvrez dans le mode opposé). (Cela signifie également que cela ne fonctionne pas pour les sockets par exemple que vous ne pouvez pas ouvrir () ).
Donc, sous Linux, quand vous le faites
exec 5<> file
echo test >&5
Le décalage du fd 5 est à la fin du fichier. Si tu fais
cat <&5
Vous n'obtenez rien.
Toujours quand vous le faites:
cat /dev/fd/5
Vous voyez, testcar catobtient un nouveau fd en lecture seule filesans rapport avec fd 5.
Sur d'autres systèmes,
cat /dev/fd/5
cat obtient un fd qui est un double de fd 5, donc toujours avec un décalage à la fin du fichier.
La raison pour laquelle cela fonctionne lessest que pour une raison quelconque, lessfait un lseek()sur ce fd au début du fichier (fait un lseek(1); lseek(0)pour déterminer si le fichier est consultable ou non).
Ici, vous voulez probablement avoir un fd pour la lecture et un pour l'écriture si vous voulez que les deux aient des décalages différents:
exec 5< file 9>&1 > file
Ou vous devrez rouvrir le fichier s'il est toujours là, ou faire lseek()comme lessça.
ksh93et zshsont les seuls shells avec un lseek()opérateur intégré cependant:
cat <&5 <#((0)) # ksh93
{sysseek 0; cat} <&5 # zsh, zmodload zsh/system to enable that builtin
Ou:
cat /dev/fd/5 5<#((0)) # ksh93
sysseek -u 5 0; cat /dev/fd/5 # zsh