No OS X, como em todos os sistemas em que eles são suportados, exceto no Linux , a abertura /dev/fd/x
é como a dup(x)
, o fd resultante aponta mais ou menos para a mesma descrição de arquivo aberto que no fd x e, em particular, terá o mesmo deslocamento no arquivo.
Linux é a exceção aqui. No Linux, /dev/fd/x
é um link simbólico para /proc/self/fd/x
e /proc/self/fd/x
é um pseudo-link simbólico para o arquivo aberto no fd x. No Linux, quando você faz um open("/dev/fd/x", somemode)
, você obtém uma nova descrição de arquivo aberto para o mesmo arquivo que o aberto x
. O novo fd que você obtém não está relacionado a fd x de forma alguma. Em particular, o deslocamento será no início do arquivo (exceto se você o abrir O_APPEND
naturalmente) e o modo (leitura / gravação / anexação ...) poderá ser diferente daquele no arquivo fd x (você pode até obter algo bem diferente do que está no fd x, como a outra extremidade do tubo ao abri-lo no modo oposto). (Isso também significa que isso não funciona para soquetes, por exemplo, que você não pode abrir () ).
Então, no Linux, quando você faz
exec 5<> file
echo test >&5
O deslocamento do fd 5 está no final do arquivo. Se você fizer
cat <&5
Você não ganha nada.
Ainda quando você faz:
cat /dev/fd/5
Você vê test
porque cat
um novo fd somente leitura é file
relacionado ao fd 5.
Em outros sistemas, mediante
cat /dev/fd/5
cat
obtém um fd que é uma duplicata do fd 5, portanto, ainda com um deslocamento no final do arquivo.
A razão pela qual ele trabalha less
é que, por algum motivo, less
faz um lseek()
nesse fd até o início do arquivo (faz um lseek(1); lseek(0)
para determinar se o arquivo é procurável ou não).
Aqui, você provavelmente deseja ter um fd para leitura e outro para escrever se quiser que ambos tenham desvios diferentes:
exec 5< file 9>&1 > file
Ou você terá que reabrir o arquivo, se ainda estiver lá, ou fazer o lseek()
que less
faz.
ksh93
e zsh
são os únicos shells com um lseek()
operador interno :
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