Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

It can be done with other tools, but I am interested to know how can I delete all but the last X lines of the file with sed.

share|improve this question
The hard way. Stick with the other tools. – Ignacio Vazquez-Abrams Sep 7 '12 at 2:22

Basically you are emulating tail. X = 20 in this example. The following example will delete all but the last 20 lines:

sed -e :a -e '$q;N;21,$D;ba' filename


  • The -e :a creates a label called a
  • The next -e:
    • $q - quits and prints the pattern space if it is the last line
    • N - next line
    • 21,$D - executes the "D" command if the line# is >= 21 (21,$ = 21st line to $ which is the end of the file)
    • ba - branches to label 'a' which is the beginning of the script.
share|improve this answer
It works as tail, but I was not able to make it work in place (as the in the original question) – Matteo Sep 7 '12 at 6:48
+1... BTW. It works with -i if you condense the two -e expressions into one. You can also use it by passing bash variable $1 into it... sed -i ':a;$q;N;'$(($1+1))',$D;ba' filename ... but asking for 0 lines, will return 1 line. – Peter.O Sep 7 '12 at 7:42

sed is quite complex when it comes to task like this one. tail, grep or awk would make this a lot easier and should be used instead. That being said, it is possible.

The following solution is adapted from sed and Multi-Line Search and Replace.

sed -ni '
    # if the first line copy the pattern to the hold buffer
    # if not the first line then append the pattern to the hold buffer
    # if the last line then ...
            # copy from the hold to the pattern buffer
            # delete current line if it is followed by at least X more lines
            # replace X-1 with the proper value
            # print
' filename

Without the comments, it makes a nifty one-liner. If you want to eliminate, e.g., everything but the last ten lines, use this:

sed -ni '1h;1!H;${;g;s/.*\n\(\(.*\n\)\{9\}\)/\1/;p;}' filename
share|improve this answer
On non-GNU seds you need -e after -i. – Matteo Sep 7 '12 at 6:46
Just like phiz's answer, this does not handle a request for 0 last lines... However, that is one of the reasons for the recommendation to use another tool. – Peter.O Sep 7 '12 at 7:49

Based on the script in section 4.13 of the manual you could do something like this:


(( n > 1 )) && script='1h; 2,'$n'{H;g;}; $q; 1,'$((n-1))'d; N; D'
(( n > 1 )) || script='$!d'

sed -i "$script" infile
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.