How to output all the lines except the last one in console

Here is the task. There is some text in console. It can be the content of a file or a result of some sommand. Beforehand it is not known how many lines there are in that text. The task is to output all the lines, but the last one.

The most simple way to do it in Linux is to use head command and to pass it negative number as a value for the -n parameter.

Here is an example. There is a command that outputs three lines to the screen:

$ echo -e '1\n2\n3'
1
2
3

We're passing -1 (minus one) as the value for the -n paramter for the head comand and we get all the lines but the last one:

$ echo -e '1\n2\n3' | head -n -1
1
2

And you can pass not only -1 (to get all the lines but the last one), but also -2 (to get all the lines except two last lines), but also -3 (to get all the lines except the last three) and so on.

Of caurse, if you know in advance the total number of the lines, you can use not the negative number, but the positive number. Just say — show the first two lines:

$ echo -e '1\n2\n3' | head -n 2
1
2

But the negative values is very usefull when it is not known in advance how much lines should be parsed.

Here is the fragment of the head command help that describes the -n parameter:

$ head --help

...

  -n, --lines=[-]NUM       print the first NUM lines instead of the first 10;
                           with the leading '-', print all but the last
                           NUM lines of each file

It's a pity, but on macOS the negative values of -n parameter does not work. The macOS system has BSD version of head (there is GNU version on linus) and you get an error when you enter the negative value for the -n parameter:

$ echo -e '1\n2\n3' | head -n -1
head: illegal line count -- -1

One of possible solutions is to use such one-lines on macOS to output all the lines but the last one:

$ echo -e '1\n2\n3' | perl -nalE 'push(@lines, $_); }{ say $lines[$_] foreach 0..$#lines -1'
1
2

(at the very end of this one-liner there is a number -1. If it is needed to output all the lines, but the last two you should write -2 instead of -1, if you need to output all the lines but the last three you should write -3, and so on)

The other possible solution on macOS is to install package coreutils with Homebrew package manager:

$ brew install coreutils

And then use ghead command with the negative value of -n parameter:

$ echo -e '1\n2\n3' | ghead -n -1
1
2

Ivan Bessarabov
ivan@bessarabov.ru

9 march 2019

This text is also available in Russian language