O problema é que esses arquivos /proc
no Linux aparecem como arquivos de texto no que diz respeito a stat()/fstat()
, mas não se comportam como tal.
Como são dados dinâmicos, você só pode fazer uma chamada read()
do sistema neles (pelo menos para alguns deles). Fazendo mais do que um poderia obter dois pedaços de dois conteúdos diferentes, então, em vez disso, parece um segundo read()
neles apenas não retorna nada (ou seja, fim de arquivo) (a menos que vocêlseek()
volta para o início (e para o começando apenas)).
O utilitário read
precisa ler o conteúdo dos arquivos um byte de cada vez para ter certeza de não ler além do caractere de nova linha. Isso é o que o dash
faz:
$ strace -fe read dash -c 'read a < /proc/sys/fs/file-max'
read(0, "1", 1) = 1
read(0, "", 1) = 0
Alguns shells como bash
têm uma otimização para evitar a necessidade de fazer tantas chamadas de sistema read()
. Primeiro, eles verificam se o arquivo é pesquisável e, em caso afirmativo, leem em blocos e, em seguida, eles sabem que podem colocar o cursor de volta logo após a nova linha, se tiverem lido o texto:
$ strace -e lseek,read bash -c 'read a' < /proc/sys/fs/file-max
lseek(0, 0, SEEK_CUR) = 0
read(0, "1628689\n", 128) = 8
Com bash
, você ainda terá problemas com arquivos proc maiores do que 128 bytes e que só podem ser lidos em uma chamada de sistema lida.
bash
também parece desativar essa otimização quando a opção -d
é usada.
ksh93
leva a otimização ainda mais a ponto de se tornar falsa. O read
de ksh93 procura novamente, mas lembra-se dos dados extras que leu para o próximo read
, então o próximo read
(ou qualquer um de seus outros integrantes que leiam dados como cat
ou head
) não faz • nem tente read
dos dados (mesmo que esses dados tenham sido modificados por outros comandos intermediários):
$ seq 10 > a; ksh -c 'read a; echo test > a; read b; echo "$a $b"' < a
1 2
$ seq 10 > a; sh -c 'read a; echo test > a; read b; echo "$a $b"' < a
1 st