Sign up ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Is there a way to head/tail a document and get the reverse output; because you don't know how many lines there are in a document?

I.e. I just want to get everything but the first 2 lines of foo.txt to append to another document.

share|improve this question

8 Answers 8

up vote 31 down vote accepted

You can use this to strip the first two lines:

tail -n +3 foo.txt

and this to strip the last two lines:

head -n -2 foo.txt

(assuming the file ends with \n for the latter)

Just like for the standard usage of tail and head these operations are not destructive. Use >out.txt if you want to redirect the output to some new file:

tail -n +3 foo.txt >out.txt

In the case out.txt already exists, it will overwrite this file. Use >>out.txt instead of >out.txt if you'd rather have the output appended to out.txt.

share|improve this answer
re "head, when file ends with \n".. It works for all negative integers other than -n -0 which returns nothing at all, just as -n 0 would (using: head (GNU coreutils) 7.4) ... However when a trailing \n is present, -n -0 does print as might be expected from the -, ie. it prints the entire file... So it does work for all non-zero negative values.. but -0 fails when there is no trailing \n –  Peter.O Aug 16 '11 at 6:16
@fred: Strange indeed… (same with 8.12 here). –  Stéphane Gimenez Aug 16 '11 at 9:21
Is this operation destructive? As i want it to copy the inverse of the first two lines of the document to another? –  chrisjlee Aug 16 '11 at 14:29
@Chris: No, they just print the result on their "standard output", which is usually connected to the terminal. I've added some details on how to redirect the output to some files. –  Stéphane Gimenez Aug 16 '11 at 15:05
head -n -2 is not POSIX compatible. –  l0b0 May 15 '13 at 13:56

If you want all but the first N-1 lines, call tail with the number of lines +N. (The number is the number of the first line you want to retain, starting at 1, i.e. +1 means start at the top, +2 means skip one line and so on).

tail -n +3 foo.txt >>other-document

There's no easy, portable way to skip the last N lines. GNU head allows head -n +N as a counterpart of tail -n +N. Otherwise, if you have tac (e.g. GNU or Busybox), you can combine it with tail:

tac | tail -n +3 | tac

Portably, you can use an awk filter (untested):

awk -vskip=2 '{
    lines[NR] = $0;
    if (NR > skip) print lines[NR-skip];
    delete lines[NR-skip];

If you want to remove the last few lines from a large file, you can determine the byte offset of the piece to truncate then perform the truncation with dd.

total=$(wc -c < /file/to/truncate)
chop=$(tail -n 42 /file/to/truncate | wc -c)
dd if=/dev/null of=/file/to/truncate seek=1 bs="$((total-chop))"

You can't truncate a file in place at the beginning, though if you need to remove the first few lines of a huge file, you can move the contents around.

share|improve this answer
On some systems (like modern Linux), you can truncate (collapse) a file in place at the beginning, but usually only by an amount that is multiple of the FS block size (so not really useful in this case). –  Stéphane Chazelas May 19 at 16:49

From the tail man page (GNU tail, that is):

-n, --lines=K
   output the last K lines, instead of the last 10; or use -n +K to
   output lines starting with the Kth

Thus, the following should append all but the first 2 lines of somefile.txt to anotherfile.txt:

tail --lines=+3 somefile.txt >> anotherfile.txt
share|improve this answer

To remove the first n lines GNU sed can be used. For example if n = 2

sed -n '1,2!p' input-file

The ! mean "exclude this interval". As you can imagine, more complicated result can be obtained, for example

sed -n '3,5p;7p'

that will show line 3,4,5,7. More power come from use of regular expressions instead of addresses.

The limitation is that the lines numbers must be known in advance.

share|improve this answer

You can use diff to compare the output of head/tail to the original file and then remove what is the same, therefore getting the inverse.

diff --unchanged-group-format='' foo.txt <(head -2 foo.txt)
share|improve this answer

While tail -n +4 to output the file starting at the 4th line (all but the first 3 lines) is standard and portable, its head counterpart (head -n -3, all but the last 3 lines) is not.

Portably, you'd do:

sed '$d' | sed '$d' | sed '$d'


sed -ne :1 -e '1,3{N;b1' -e '}' -e 'P;N;D'

(beware that on some systems where sed has a pattern space of limited size, that doesn't scale to large values of n).


awk 'NR>3 {print l[NR%3]}; {l[NR%3]=$0}'
share|improve this answer
{   head -n2 >/dev/null
    cat  >> other_document
}   <infile

If <infile is a regular, lseek()-able file, then yes, by all means, feel free. The above is a fully POSIXly supported construct.

share|improve this answer

Hope I clearly understood your need.

You've several ways to complete your request :

tail -n$(expr $(cat /etc/passwd|wc -l) - 2) /etc/passwd

Where /etc/passwd is your file

The 2nd solution may be usefull if you have huge file:

my1stline=$(head -n1 /etc/passwd)
my2ndline=$(head -n2 /etc/passwd|grep -v "$my1stline")
cat /etc/passwd |grep -Ev "$my1stline|$my2ndline"

Hope it helps

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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