В OS X, как и во всех системах, где они поддерживаются, кроме Linux , открытие /dev/fd/x
похоже на выполнение a dup(x)
, результирующий fd более или менее указывает на то же описание открытого файла, что и на fd x, и, в частности, будет иметь такое же смещение внутри файла.
Linux здесь исключение. В Linux /dev/fd/x
это символическая ссылка /proc/self/fd/x
и /proc/self/fd/x
псевдосимвольная ссылка на файл, открытый на fd x. В Linux, когда вы делаете a open("/dev/fd/x", somemode)
, вы получаете совершенно новое описание открытого файла в том же файле, что и open x
. Новый полученный вами fd никак не связан с fd x. В частности, смещение будет в начале файла (кроме случаев, когда вы, O_APPEND
конечно, открываете его ), а режим (чтение / запись / добавление ...) может отличаться от режима на fd x (вы даже можете получить нечто совершенно отличное от того, что есть на fd x, например, другой конец трубы при открытии в противоположном режиме). (Это также означает, что это не работает для сокетов, например, которые вы не можете открыть () ).
Итак, в Linux, когда вы делаете
exec 5<> file
echo test >&5
Смещение fd 5 находится в конце файла. Если вы делаете
cat <&5
Вы ничего не получите.
Тем не менее, когда вы делаете:
cat /dev/fd/5
Вы видите, test
потому что cat
получает новый доступный только для чтения fd, file
не связанный с fd 5.
В других системах, после
cat /dev/fd/5
cat
получает fd, который является дубликатом fd 5, поэтому все еще со смещением в конце файла.
Причина, по которой он работает, less
заключается в том, что по какой-то причине less
выполняет lseek()
поиск в этом файле до начала файла (делает, lseek(1); lseek(0)
чтобы определить, является ли файл доступным для поиска или нет).
Здесь вы, вероятно, хотите иметь fd для чтения и один для записи, если вы хотите, чтобы оба имели разные смещения:
exec 5< file 9>&1 > file
Или вам придется заново открыть файл, если он все еще там, или сделать lseek()
как less
.
ksh93
и zsh
являются единственными оболочками со встроенным lseek()
оператором:
cat <&5 <#((0)) # ksh93
{sysseek 0; cat} <&5 # zsh, zmodload zsh/system to enable that builtin
Или:
cat /dev/fd/5 5<#((0)) # ksh93
sysseek -u 5 0; cat /dev/fd/5 # zsh