4

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.

1 Answer 1

4

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.

4
  • @StephaneChazelas, GNU head -n -1 needs also one line of storage (or two depending what you are really counting). And doesn't fail here. May 15, 2013 at 15:25
  • I highly doubt any implementation of head or tail actually stores the lines; it would simply have to store the position in the file. As you say, starting from EOF, look backwards to find the Nth newline. Record the position and print the entire file until that position. Not exactly resource intensive: time head -n +10 [88 MB file on a harddisk] reports 0.002s. And who's to say whether a feature is "worth implementing?"
    – l0b0
    May 15, 2013 at 15:42
  • 1
    @l0b0, but it needs to work on non-seekable pipes, so it can't depend on seek. (It might have an optimization for seekable files, but it must have a fallback.)
    – cjm
    May 15, 2013 at 15:59
  • @cjm I forgot about non-seekable streams :) I still can't believe excluding the last N lines is much more rare than excluding the first N lines. I'd upvote your answer if it wasn't for the first paragraph and the caveat about seekable streams.
    – l0b0
    May 16, 2013 at 7:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.