POSIX head and tail not feature equivalent

headposixtail

The documentation for POSIX tail's -n option says that

The origin for counting shall be 1; that is, -n +1 represents the first line of the file, -n -1 the last.

So tail -n 10 (used later on the same page) and tail -n -10 should print the last ten lines, and tail -n +10 would skip the first nine lines and print all the rest.

The documentation for POSIX head's -n option says that

The application shall ensure that the number option-argument is a positive decimal integer.

So head -n -10 and head -n +10 are not POSIX compatible because the values -10 and +10 are not simple integers but rather strings with no special meaning in the shell, and there's no way to print all lines until the Nth last one. Why the discrepancy?

PS: head -n +10 works with GNU coreutils.

Best Answer

Because nobody thought that the feature you're looking for was worth implementing, so there's no syntax to request it.

Consider how that would need to be implemented. First, you'd have to seek to the end of the file, scan backwards to figure out where the Nth last line begins, make a note of that position, seek back to the beginning, and then print lines until you reach the position you remembered. That's far more complicated than what head normally does. (Alternatively, you could read the entire file into memory, drop the N last lines, and print the rest.) More importantly though, it wouldn't work with unseekable streams.

On the other hand, tail's features are fairly simple to implement. It never needs to store more than N lines (in the -n -N case). For the -n +N case it just needs to count how many lines to skip before it starts printing them.

Related Question