Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Move last n lines of a text file to the top with Bash

Tags:

bash

command

sed

How can I move last n lines of a text file to the top without knowing number of lines of the file? Is it possible to achieve this with single command line (with sed for example)?

From:

...
a
b
c
d

To:

a
b
c
d
...
like image 378
user671162 Avatar asked Oct 18 '25 11:10

user671162


2 Answers

Updated 2021:

Using vim's ex mode is even simpler: (inspired by this answer)

vim -        -esc '$-3,$m0|%p|q!' --not-a-term  # when processing a pipe
vim file.txt -esc '$-3,$m0|%p|q!' --not-a-term  # when processing a file to stdout
vim file.txt -esc '$-3,$m0|wq'    --not-a-term  # when editing a file inline

This will move last 4 lines (last line + 3 lines before the last line) to top. Change 3 to your desired number.

A MWE:

seq 10 | vim - '-esc$-3,$m0|%p|q!' --not-a-term

Output:

7
8
9
10
1
2
3
4
5
6

Updated 2020:

You may find it hard if the input source is from pipe. In this case, you can use

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

This will store all lines in memory (which may be an issue) and then output them. Change 4 in the command to see different results.


Display the last n lines and then display the rest:

tail -n 4 file; head -n -4 file

From man head:

-n, --lines=[-]NUM

print the first NUM lines instead of the first 10; with the leading '-', print all but the last NUM lines of each file

tail -n 4 will display the last 4 lines of a file.

If you wish to pipe this data, you need to put them together like this:

( tail -n 4 file; head -n -4 file ) | wc

Or maybe you can use vim to edit file inline:

vim +'$-3,$m0' +'wq' file

The + option for vim will run the (Ex) command following it. $-3,$m0 means move lines between 3 lines above the last line and the last line to the beginning of the file. Note that there should be no space between + and the command.


Or using commands in vim normal mode:

vim +'norm G3kdGggPZZ' file

G go to file end; 3k move up 3 lines; dG deletes to file end; gg go to file top; P pastes the deleted lines before this line; ZZ saves and quits.

like image 129
dibery Avatar answered Oct 21 '25 02:10

dibery


This might work for you (GNU sed):

sed '$!H;1h;$!d;G' file

Append every line but the last to the hold space and then append the hold space to the the last line.

like image 20
potong Avatar answered Oct 21 '25 02:10

potong



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!