head
imprime 10 linhas por padrão, mas lê o máximo de entradas possíveis - note que o GNU head
possui opções que requerem que você saiba quantas linhas existem no arquivo no total, então ler o quanto puder não é errado.
head
lê o máximo possível para preencher seu buffer, que parece ter 8192 bytes:
~ seq 10000 | strace -fe read ./foo.sh
read(3, "7ELFThe lseek() function shall fail if:
...
ESPIPE The fildes argument is associated with a pipe, FIFO, or socket.
~ seq 10000 | strace -fe lseek ./foo.sh
...
Process 18561 attached
[pid 18561] lseek(0, -8171, SEEK_CUR) = -1 ESPIPE (Illegal seek)
[pid 18561] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=18561, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
Process 18562 attached
[pid 18562] lseek(0, -8146, SEEK_CUR) = -1 ESPIPE (Illegal seek)
...
~ seq 10000 | strace -fe read ./foo.sh
read(3, "7ELFThe lseek() function shall fail if:
...
ESPIPE The fildes argument is associated with a pipe, FIFO, or socket.
~ seq 10000 | strace -fe lseek ./foo.sh
...
Process 18561 attached
[pid 18561] lseek(0, -8171, SEEK_CUR) = -1 ESPIPE (Illegal seek)
[pid 18561] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=18561, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
Process 18562 attached
[pid 18562] lseek(0, -8146, SEEK_CUR) = -1 ESPIPE (Illegal seek)
...
%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%>%pre%%pre%%pre%%pre%0e%pre%%pre%%pre%%pre%%pre%"..., 832) = 832
...
Process 17610 attached
...
[pid 17610] read(0, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14"..., 8192) = 8192
...
[pid 17611] read(0, "\n1861\n1862\n1863\n1864\n1865\n1866\n1"..., 8192) = 8192
...
%pre%%pre%%pre%%pre%%pre%%pre%%pre%>%pre%%pre%%pre%%pre%0e%pre%%pre%%pre%%pre%%pre%"..., 832) = 832
...
Process 17610 attached
...
[pid 17610] read(0, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14"..., 8192) = 8192
...
[pid 17611] read(0, "\n1861\n1862\n1863\n1864\n1865\n1866\n1"..., 8192) = 8192
...
Como as duas primeiras gravações têm 4096 bytes cada, elas podem ser consumidas pela primeira head
.
Isso depende do tempo. Se seq
só conseguiu obter um write
de distância quando o primeiro head
imprimiu 10 linhas e saiu, então o segundo write
será obtido pelo segundo head
.
O comentário do mikeserv está esclarecendo:
you should try it w/ a regular file.
seq 10000 >/tmp/nums; yourscript </tmp/nums
A razão pela qual isso se comporta como seria de esperar é que head
tenta reposicionar o ponto de leitura atual para a linha após os que ele emitiu usando lseek()
. Isso funciona para arquivos normais, arquivos redirecionados etc., mas não funciona para pipes:
Como pode ser visto usando strace
: