Ответ 1
OS X
Для OS X вы можете посмотреть исходный код для head
и исходный код для tail
, чтобы выяснить, что происходит. В случае tail
вам нужно посмотреть forward.c
.
Итак, оказывается, что head
не делает ничего особенного. Он просто считывает свои данные, используя библиотеку stdio
, поэтому он читает буфер за раз и может слишком много читать. Это означает, что cat file | (head; tail)
не будет работать для небольших файлов, где буферизация head
позволяет читать некоторые (или все) из последних 10 строк.
С другой стороны, tail
проверяет тип входного файла. Если это обычный файл, tail
подходит к концу и читает назад, пока не найдет достаточное количество строк для испускания. Вот почему (head; tail) < file
работает с любым обычным файлом независимо от его размера.
Linux
Вы можете посмотреть источник для head
и tail
на Linux тоже, но проще просто использовать strace
, например:
(strace -o /tmp/head.trace head; strace -o /tmp/tail.trace tail) < file
Взгляните на /tmp/head.trace
. Вы увидите, что команда head
пытается заполнить буфер (из 8192 байт в моем тесте), читая со стандартного ввода (дескриптор файла 0). В зависимости от размера file
он может или не может заполнять буфер. В любом случае, допустим, что он читает 10 строк в первом чтении. Затем он использует lseek
для резервного копирования дескриптора файла до конца 10-й строки, по существу "нечитающего" лишних байтов, которые он читает. Это работает, потому что файловый дескриптор открыт в обычном, доступном для поиска файле. Таким образом, (head; tail) < file
будет работать для любого файла с возможностью поиска, но он не сделает работу cat file | (head; tail)
.
С другой стороны, tail
не пытается (в моем тестировании) искать конец и читать назад, как это происходит на OS X. По крайней мере, он не читает все пути назад к началу файл.
Вот мой тест. Создайте небольшой 12-строчный входной файл:
yes | head -12 | cat -n > /tmp/file
Затем попробуйте (head; tail) < /tmp/file
в Linux. Я получаю это с GNU coreutils 5.97:
1 y
2 y
3 y
4 y
5 y
6 y
7 y
8 y
9 y
10 y
11 y
12 y
Но в OS X я получаю следующее:
1 y
2 y
3 y
4 y
5 y
6 y
7 y
8 y
9 y
10 y
3 y
4 y
5 y
6 y
7 y
8 y
9 y
10 y
11 y
12 y