Take the 2-minute tour ×

I asked a question regarding popping the last line of a text file in PHP, and now, is it possible to re-write the logic in shell script?

I tried this to obtain the last line:

tail -n 1 my_log_file.log

but I am not sure how can I remove the last line and save the file.

P.S. given that I use Ubuntu server.

share|improve this question

4 Answers 4

up vote 4 down vote accepted

(Solution is based on sch's answer so credit should go to him/her)

This approach will allow you to efficiently retrieve the last line of the file and truncate the file to remove that line. This can better deal with large inputs as the file is not read sequentially.

# retrieve last line from file
LAST=$(tail -n 1 my_log_file.log)

# truncate file
let TRUNCATE_SIZE="${#LAST} + 1"
truncate -s -"$TRUNCATE_SIZE" my_log_file.log

# ... $LAST contains 'popped' last line

Note that this will not work as expected if the file is modified between the calls to tail and truncate.

share|improve this answer
Note that contrary to the "wc" based solution I gave which would work on GNU systems, the above will only work correctly with zsh if the last line contains NUL characters. Also, it won't work correctly if the last line is not NL terminated. –  Stephane Chazelas Aug 29 '12 at 15:54

What you want is truncate the file just before the last line without having to read the file entirely.

truncate -s -"$(tail -n1 file | wc -c)" file

That's assuming the file is not currently being written to.

truncate is part of the GNU coreutils (so generally found on recent Linux distributions) and is not a standardized Unix or POSIX command. Many "dd" implementations can be used to truncate a file as well.

share|improve this answer
Using tail + truncate would indeed be a more efficient solution. Naturally, to allow the OP to retrieve the contents of the last line tail -n should be called separately and stored in a var. You can then use ${#VAR} + 1 as the truncation size. –  Shawn Chin Aug 29 '12 at 12:39
Added a wiki answer with proposed changes. –  Shawn Chin Aug 29 '12 at 12:53
There seems to be an extra - preceding the tail/wc combo. Also, you could use the -r option (use the given file's size) here: truncate -r <(tail -n1 file) file if you don't mind the bashism. –  chepner Aug 29 '12 at 13:02
Process substitution is a kshism (also supported by zsh and bash). It won't work because <(tail -n1 file) is a pipe and because we want to shave off that many files, not truncate the file to the same size as its last line. –  Stephane Chazelas Aug 29 '12 at 15:58

To get the file content without the last line, you can use

head -n-1 logfile.log

(I am not sure this is supported everywhere)


sed '$d' logfile.log
share|improve this answer

One way is:

sed '$d' < f1 > f2 ; mv f2 f1
share|improve this answer
I don't understand this. what is f2 and f1 ? –  Raptor Aug 30 '12 at 1:22
I'm late here but this is my favourite solution. You can do the change in-place using sed's "-i" flag: "sed -i -e '$d' my_log_file.log" –  Amos Shapira Oct 28 at 2:51

Your Answer


