9

Variants of this question have certainly been asked several times in different places, but I am trying to remove the last M lines from a file without luck.

The second most voted answer in this question recommends doing the following to get rid of the last line in a file:

head -n -1 foo.txt > temp.txt

However, when I try that in OSX & Zsh, I get:

head: illegal line count -- -1

Why is that? How can I remove the M last lines and the first N lines of a given file?

14

You can remove the first 12 lines with:

tail -n +13

(That means print from the 13th line.)

Some implementations of head like GNU head support:

head -n -12

but that's not standard.

tail -r file | tail -n +12 | tail -r

would work on those systems that have tail -r (see also GNU tac) but is sub-optimal.

Where n is 1:

sed '$d' file

You can also do:

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

to remove 2 lines, but that's not optimal.

You can do:

sed -ne :1  -e 'N;1,12b1' -e 'P;D'

But beware that won't work with large values of n with some sed implementations.

With awk:

awk -v n=12 'NR>n{print line[NR%n]};{line[NR%n]=$0}'

To remove m lines from the beginning and n from the end:

awk -v m=6 -v n=12 'NR<=m{next};NR>n+m{print line[NR%n]};{line[NR%n]=$0}'
  • sed 'x;1d;$d' might be used to get the last two lines as well. And w/ a couple of N's after 1d might be used to get a little more than that, though at that point it offers no advantage over the N;P;D loop you already recommend. – mikeserv Nov 21 '14 at 0:46
  • Thank you -- The last command is extremely helpful. A summer small caveat: it doesn't work when m or n are 0. Otherwise it would be perfect. – Amelio Vazquez-Reina Nov 21 '14 at 21:13
2

You can use the following way to remove first N lines and last M lines.

With N=5, M=7 and file test.txt:

sed -n -e "6,$(($(wc -l < test.txt) - 7))p" test.txt

The command prints all lines from N+1 to LastLine-M.

Another option is to use python:

python -c 'import sys;print "".join(sys.stdin.readlines()[5:-7]),' < test.txt
1

You can remove the last M (here M=100) lines from a file with:

head -$(($(wc -l < foo.txt) - 100)) foo.txt > temp.txt

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.