W OS X, podobnie jak we wszystkich systemach, w których są obsługiwane oprócz Linuksa , otwieranie /dev/fd/xjest jak robienie dup(x), wynikowy fd mniej więcej wskazuje ten sam opis otwartego pliku jak na fd x, a w szczególności będzie miał takie samo przesunięcie w pliku.
Linux jest tutaj wyjątkiem. W systemie Linux /dev/fd/xjest dowiązaniem do /proc/self/fd/xi /proc/self/fd/xjest pseudo-dowiązaniem do otwartego pliku na fd x. W systemie Linux, gdy to zrobisz open("/dev/fd/x", somemode), otrzymasz zupełnie nowy opis otwartego pliku do tego samego pliku, co otwarty x. Otrzymany nowy fd nie jest w żaden sposób powiązany z fd x. W szczególności przesunięcie będzie na początku pliku (chyba że otworzysz go O_APPENDoczywiście), a tryb (odczyt / zapis / dołącz ...) może różnić się od tego na fd x (możesz nawet uzyskać coś zupełnie innego niż na fd x, jak drugi koniec potoku podczas otwierania go w trybie przeciwnym). (Oznacza to również, że nie działa to na przykład dla gniazd, których nie można otworzyć () ).
Więc w Linuksie, kiedy to robisz
exec 5<> file
echo test >&5
Przesunięcie fd 5 znajduje się na końcu pliku. Jeśli zrobisz
cat <&5
Nic nie dostaniesz
Nadal kiedy to robisz:
cat /dev/fd/5
Widzisz, testponieważ catdostaje nowy fd tylko do odczytu, fileniezwiązany z fd 5.
W innych systemach
cat /dev/fd/5
cat dostaje fd, który jest duplikatem fd 5, więc nadal z przesunięciem na końcu pliku.
Powodem, dla którego działa, lessjest to, że z jakiegoś powodu lessrobi to lseek()na początku pliku ( lseek(1); lseek(0)sprawdza, czy plik jest widoczny).
Tutaj prawdopodobnie chcesz mieć fd do czytania i jeden do pisania, jeśli chcesz, aby oba miały różne przesunięcia:
exec 5< file 9>&1 > file
Lub będziesz musiał ponownie otworzyć plik, jeśli nadal istnieje, lub zrobić lseek()jak lessrobi.
ksh93i zshsą jedynymi powłokami z wbudowanym lseek()operatorem:
cat <&5 <#((0)) # ksh93
{sysseek 0; cat} <&5 # zsh, zmodload zsh/system to enable that builtin
Lub:
cat /dev/fd/5 5<#((0)) # ksh93
sysseek -u 5 0; cat /dev/fd/5 # zsh