The head/tail specifications refer to line/byte offsets as
offsets within *files* as opposed to *input*.

Does it mean that:

{ head -n 1; head -n 1; } < file
{ tail -n 1; tail -n 1; } < file

are required to print the first/last line of "file" twice
(assuming "file" is seekable and is not modified between the two
head/tail invocations)?

In the case of "head", I can't find any implementation that
does, they all return the first line of their *input* as opposed
to the first line of whatever file may be open on stdin.

However, in the case of "tail", for seekable stdin, traditional
implementations used to seek to the end of the file open on
stdin and look backward for the last line from there even if the
initial position of stdin was past the start of that last line
(it could even be past the end of the file).

That was fixed in GNU tail in 1995 and in ksh93's tail builtin
in 2006 (AFAICT), but not in many other implementations (I had a
vague recollection that busybox tail had been fixed as well at
some point, but either they have reverted it, or it was bad
memory on my part).

The tail of Solaris 10, FreeBSD, OpenBSD still output the last
line twice in

{ tail -n 1; tail -n 1; } < file

(but not in cat file | { tail -n 1; tail -n 1; } of course).

IMO, both head/tail without file arguments should give the head
and tail of their input and the fact that some tail
implementations may end up rewinding their stdin is an overlook
on their part. But it looks like POSIX doesn't agree with me,
though it looks like a similar overlook, (or possibly there's
text somewhere else that covers that case?).


Reply via email to