[linux] 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.

This question is related to linux bash shell sed

The answer is


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 !!)


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

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


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


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.


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

posix version


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.


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)

In docker, this worked for me:

head --lines=-N file_path >> file_path

This will remove the last 12 lines

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

To delete last 4 lines:

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

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

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

This will remove the last 3 lines from file:

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


This might work for you (GNU sed):

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

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

I prefer this solution;

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

where N is the number of lines to remove.


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'

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!).


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".


Try the following command:

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

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

Examples related to linux

grep's at sign caught as whitespace How to prevent Google Colab from disconnecting? "E: Unable to locate package python-pip" on Ubuntu 18.04 How to upgrade Python version to 3.7? Install Qt on Ubuntu Get first line of a shell command's output Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running? Run bash command on jenkins pipeline How to uninstall an older PHP version from centOS7 How to update-alternatives to Python 3 without breaking apt?

Examples related to bash

Comparing a variable with a string python not working when redirecting from bash script Zipping a file in bash fails How do I prevent Conda from activating the base environment by default? Get first line of a shell command's output Fixing a systemd service 203/EXEC failure (no such file or directory) /bin/sh: apt-get: not found VSCode Change Default Terminal Run bash command on jenkins pipeline How to check if the docker engine and a docker container are running? How to switch Python versions in Terminal?

Examples related to shell

Comparing a variable with a string python not working when redirecting from bash script Get first line of a shell command's output How to run shell script file using nodejs? Run bash command on jenkins pipeline Way to create multiline comments in Bash? How to do multiline shell script in Ansible How to check if a file exists in a shell script How to check if an environment variable exists and get its value? Curl to return http status code along with the response docker entrypoint running bash script gets "permission denied"

Examples related to sed

Retrieve last 100 lines logs How to replace multiple patterns at once with sed? Insert multiple lines into a file after specified pattern using shell script Linux bash script to extract IP address Ansible playbook shell output remove white space from the end of line in linux bash, extract string before a colon invalid command code ., despite escaping periods, using sed RE error: illegal byte sequence on Mac OS X How to use variables in a command in sed?