Is it correct for the head utility to consume more characters from the input stream than it was asked?
Sim, é permitido (veja abaixo).
Is there some kind of standard for Unix utilities?
Sim, POSIX volume 3, Shell & Utilitários .
And if there is, does it specify this behavior?
Na sua introdução:
When a standard utility reads a seekable input file and terminates without an error before it reaches end-of-file, the utility shall ensure that the file offset in the open file description is properly positioned just past the last byte processed by the utility. For files that are not seekable, the state of the file offset in the open file description for that file is unspecified.
head
é um dos utilitários padrão , portanto, uma implementação em conformidade com POSIX para implementar o comportamento descrito acima.
O GNU head
faz tentar deixar o descritor de arquivo na posição correta, mas é impossível procurar em canais, portanto, em seu teste, ele não consegue restaurar a posição. Você pode ver isso usando strace
:
$ echo -e "aaa\nbbb\nccc\nddd\n" | strace head -n 1
...
read(0, "aaa\nbbb\nccc\nddd\n\n", 8192) = 17
lseek(0, -13, SEEK_CUR) = -1 ESPIPE (Illegal seek)
...
O read
retorna 17 bytes (toda a entrada disponível), head
processa quatro desses e depois tenta voltar 13 bytes, mas não consegue. (Você também pode ver aqui que o GNU head
usa um buffer de 8 KiB.)
Quando você diz head
para contar bytes (que não é padrão), ele sabe quantos bytes ler, então pode (se implementado dessa forma) limitar sua leitura de acordo. É por isso que seu teste head -c 5
funciona: o GNU head
só lê cinco bytes e, portanto, não precisa restaurar a posição do descritor de arquivo.
Se você gravar o documento em um arquivo e usá-lo, verá o comportamento que deseja:
$ echo -e "aaa\nbbb\nccc\nddd\n" > file
$ < file (while true; do head -n 1; head -n 1 >/dev/null; done)
aaa
ccc