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