Unter OS X, wie auf allen Systemen, auf denen sie unterstützt werden, mit Ausnahme von Linux , ist das Öffnen /dev/fd/x
wie 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/x
ein Symlink zu /proc/self/fd/x
und /proc/self/fd/x
eine 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_APPEND
natü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, test
weil cat
ein neues schreibgeschütztes fd file
nicht 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, less
ist, dass aus irgendeinem Grund less
a 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 less
ausführen.
ksh93
und zsh
sind 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