Unter OS X, wie auf allen Systemen, auf denen sie unterstützt werden, mit Ausnahme von Linux , ist das Öffnen /dev/fd/xwie bei a dup(x). Das resultierende fd zeigt mehr oder weniger auf dieselbe Beschreibung der geöffneten Datei wie auf fd x und hat insbesondere den gleichen Versatz innerhalb der Datei.
Linux ist hier die Ausnahme. Ist unter Linux /dev/fd/xein Symlink zu /proc/self/fd/xund /proc/self/fd/xeine Pseudo-Symlink zu der auf fd x geöffneten Datei. Wenn Sie unter Linux open("/dev/fd/x", somemode)eine ausführen, erhalten Sie eine brandneue Beschreibung der geöffneten Datei für dieselbe Datei wie beim Öffnen x. Das neue fd, das Sie erhalten, ist in keiner Weise mit fd x verbunden. Insbesondere befindet sich der Offset am Anfang der Datei (außer wenn Sie sie O_APPENDnatürlich mit öffnen ) und der Modus (Lesen / Schreiben / Anhängen ...) kann sich von dem auf fd x unterscheiden (Sie können ihn sogar erhalten etwas ganz anderes als das, was sich auf fd x befindet, wie das andere Ende des Rohrs, wenn es im entgegengesetzten Modus geöffnet wird). (Das bedeutet auch, dass dies beispielsweise für Sockets nicht funktioniert, die Sie nicht öffnen können () ).
Also, unter Linux, wenn Sie es tun
exec 5<> file
echo test >&5
Der Versatz des fd 5 befindet sich am Ende der Datei. Wenn Sie tun
cat <&5
Du bekommst nichts.
Immer noch, wenn Sie:
cat /dev/fd/5
Sie sehen, testweil catein neues schreibgeschütztes fd filenicht mit fd 5 zusammenhängt.
Auf anderen Systemen auf
cat /dev/fd/5
cat erhält eine fd, die ein Duplikat von fd 5 ist, also immer noch mit einem Versatz am Ende der Datei.
Der Grund, warum es funktioniert, lessist, dass aus irgendeinem Grund lessa lseek()auf diesem fd bis zum Anfang der Datei ausgeführt wird (führt a aus, lseek(1); lseek(0)um festzustellen, ob die Datei durchsuchbar ist oder nicht).
Hier möchten Sie wahrscheinlich einen fd zum Lesen und einen zum Schreiben haben, wenn beide unterschiedliche Offsets haben sollen:
exec 5< file 9>&1 > file
Oder Sie müssen die Datei erneut öffnen, wenn sie noch vorhanden ist, oder eine lseek()Aktion lessausführen.
ksh93und zshsind die einzigen Shells mit einem eingebauten lseek()Operator:
cat <&5 <#((0)) # ksh93
{sysseek 0; cat} <&5 # zsh, zmodload zsh/system to enable that builtin
Oder:
cat /dev/fd/5 5<#((0)) # ksh93
sysseek -u 5 0; cat /dev/fd/5 # zsh