'How to use sed to remove the last n lines of a file

I want to remove some n lines from the end of a file. Can this be done using sed?

For example, to remove lines from 2 to 4, I can use

$ sed '2,4d' file

But I don't know the line numbers. I can delete the last line using

$sed $d file

but I want to know the way to remove n lines from the end. Please let me know how to do that using sed or some other method.



Solution 1:[1]

I don't know about sed, but it can be done with head:

head -n -2 myfile.txt

Solution 2:[2]

If hardcoding n is an option, you can use sequential calls to sed. For instance, to delete the last three lines, delete the last one line thrice:

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

Solution 3:[3]

From the sed one-liners:

# delete the last 10 lines of a file
sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # method 1
sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # method 2

Seems to be what you are looing for.

Solution 4:[4]

A funny & simple sed and tac solution :

n=4
tac file.txt | sed "1,$n{d}" | tac

NOTE

  • double quotes " are needed for the shell to evaluate the $n variable in sed command. In single quotes, no interpolate will be performed.
  • tac is a cat reversed, see man 1 tac
  • the {} in sed are there to separate $n & d (if not, the shell try to interpolate non existent $nd variable)

Solution 5:[5]

Use sed, but let the shell do the math, with the goal being to use the d command by giving a range (to remove the last 23 lines):

sed -i "$(($(wc -l < file)-22)),\$d" file

To remove the last 3 lines, from inside out:

$(wc -l < file)

Gives the number of lines of the file: say 2196

We want to remove the last 23 lines, so for left side or range:

$((2196-22))

Gives: 2174 Thus the original sed after shell interpretation is:

sed -i '2174,$d' file

With -i doing inplace edit, file is now 2173 lines!

If you want to save it into a new file, the code is:

sed -i '2174,$d' file > outputfile

Solution 6:[6]

You could use head for this.

Use

$ head --lines=-N file > new_file

where N is the number of lines you want to remove from the file.

The contents of the original file minus the last N lines are now in new_file

Solution 7:[7]

Just for completeness I would like to add my solution. I ended up doing this with the standard ed:

ed -s sometextfile <<< $'-2,$d\nwq'

This deletes the last 2 lines using in-place editing (although it does use a temporary file in /tmp !!)

Solution 8:[8]

To truncate very large files truly in-place we have truncate command. It doesn't know about lines, but tail + wc can convert lines to bytes:

file=bigone.log
lines=3
truncate -s -$(tail -$lines $file | wc -c) $file

There is an obvious race condition if the file is written at the same time. In this case it may be better to use head - it counts bytes from the beginning of file (mind disk IO), so we will always truncate on line boundary (possibly more lines than expected if file is actively written):

truncate -s $(head -n -$lines $file | wc -c) $file

Handy one-liner if you fail login attempt putting password in place of username:

truncate -s $(head -n -5 /var/log/secure | wc -c) /var/log/secure

Solution 9:[9]

This might work for you (GNU sed):

sed ':a;$!N;1,4ba;P;$d;D' file

Solution 10:[10]

Most of the above answers seem to require GNU commands/extensions:

    $ head -n -2 myfile.txt
    -2: Badly formed number

For a slightly more portible solution:

     perl -ne 'push(@fifo,$_);print shift(@fifo) if @fifo > 10;'

OR

     perl -ne 'push(@buf,$_);END{print @buf[0 ... $#buf-10]}'

OR

     awk '{buf[NR-1]=$0;}END{ for ( i=0; i < (NR-10); i++){ print buf[i];} }'

Where "10" is "n".

Solution 11:[11]

With the answers here you'd have already learnt that sed is not the best tool for this application.

However I do think there is a way to do this in using sed; the idea is to append N lines to hold space untill you are able read without hitting EOF. When EOF is hit, print the contents of hold space and quit.

sed -e '$!{N;N;N;N;N;N;H;}' -e x

The sed command above will omit last 5 lines.

Solution 12:[12]

It can be done in 3 steps:

a) Count the number of lines in the file you want to edit:

 n=`cat myfile |wc -l`

b) Subtract from that number the number of lines to delete:

 x=$((n-3))

c) Tell sed to delete from that line number ($x) to the end:

 sed "$x,\$d" myfile

Solution 13:[13]

You can get the total count of lines with wc -l <file> and use

head -n <total lines - lines to remove> <file>

Solution 14:[14]

Try the following command:

n = line number
tail -r file_name | sed '1,nd' | tail -r

Solution 15:[15]

This will remove the last 3 lines from file:

for i in $(seq 1 3); do sed -i '$d' file; done;

Solution 16:[16]

I prefer this solution;

head -$(gcalctool -s $(cat file | wc -l)-N) file

where N is the number of lines to remove.

Solution 17:[17]

sed -n ':pre
1,4 {N;b pre
    }
:cycle
$!{P;N;D;b cycle
  }' YourFile

posix version

Solution 18:[18]

To delete last 4 lines:

$ nl -b a file | sort -k1,1nr | sed '1, 4 d' | sort -k1,1n | sed 's/^ *[0-9]*\t//'   

Solution 19:[19]

I came up with this, where n is the number of lines you want to delete:

count=`wc -l file`
lines=`expr "$count" - n`
head -n "$lines" file > temp.txt
mv temp.txt file
rm -f temp.txt

It's a little roundabout, but I think it's easy to follow.

  1. Count up the number of lines in the main file
  2. Subtract the number of lines you want to remove from the count
  3. Print out the number of lines you want to keep and store in a temp file
  4. Replace the main file with the temp file
  5. Remove the temp file

Solution 20:[20]

For deleting the last N lines of a file, you can use the same concept of

$ sed '2,4d' file

You can use a combo with tail command to reverse the file: if N is 5

$ tail -r file | sed '1,5d' file | tail -r > file

And this way runs also where head -n -5 file command doesn't run (like on a mac!).

Solution 21:[21]

#!/bin/sh

echo 'Enter the file name : '
read filename

echo 'Enter the number of lines from the end that needs to be deleted :'
read n

#Subtracting from the line number to get the nth line
m=`expr $n - 1`

# Calculate length of the file
len=`cat $filename|wc -l`

#Calculate the lines that must remain
lennew=`expr $len - $m`

sed "$lennew,$ d" $filename

Solution 22:[22]

A solution similar to https://stackoverflow.com/a/24298204/1221137 but with editing in place and not hardcoded number of lines:

n=4
seq $n | xargs -i sed -i -e '$d' my_file

Solution 23:[23]

In docker, this worked for me:

head --lines=-N file_path > file_path

Solution 24:[24]

Say you have several lines:

    $ cat <<EOF > 20lines.txt
> 1
> 2
> 3
[snip]
> 18
> 19
> 20
> EOF

Then you can grab:

# leave last 15 out
$ head -n5 20lines.txt
1
2
3
4
5

# skip first 14
$ tail -n +15 20lines.txt
15
16
17
18
19
20

Solution 25:[25]

This will remove the last 12 lines

sed -n -e :a -e '1,10!{P;N;D;};N;ba'