No OS X, como em todos os sistemas em que são suportados exceto Linux , abrir /dev/fd/x
é como fazer um dup(x)
, o fd resultante aponta mais ou menos para a mesma descrição de arquivo aberto como em fd x e, em particular, terá o mesmo offset dentro do arquivo.
O 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-symlink 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 do arquivo aberto para o mesmo arquivo que está aberto em 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ê abrir com O_APPEND
é claro) e o modo (leitura / gravação / anexação ...) pode ser diferente daquele em fd x (você pode até obter algo bastante 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 sockets, 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
obtém um novo fd somente leitura para file
não relacionado ao fd 5.
Em outros sistemas, após
cat /dev/fd/5
cat
obtém um fd que é uma duplicata do fd 5, portanto ainda com um deslocamento no final do arquivo.
O motivo pelo qual ele funciona com less
é que, por algum motivo, less
faz um lseek()
nesse fd para o início do arquivo (faz um lseek(1); lseek(0)
para determinar se o arquivo é procurado ou não ).
Aqui, você provavelmente deseja ter um fd para leitura e um para escrever, se quiser que ambos tenham diferentes deslocamentos:
exec 5< file 9>&1 > file
Ou você terá que reabrir o arquivo, se ainda estiver lá, ou fazer um lseek()
como less
.
ksh93
e zsh
são os únicos shells com um operador lseek()
incorporado:
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