'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 insed
command. In single quotes, no interpolate will be performed. tac
is acat
reversed, seeman 1 tac
- the
{}
insed
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.
- Count up the number of lines in the main file
- Subtract the number of lines you want to remove from the count
- Print out the number of lines you want to keep and store in a temp file
- Replace the main file with the temp file
- 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'
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow