[ale] Move last line of a file to first line

559 views
Skip to first unread message

Lightner, Jeff

unread,
Mar 28, 2012, 11:10:17 AM3/28/12
to Atlanta Linux Enthusiasts

We have variable length text files being received in which the “header” line we use in automated processing is the last line of the file rather than the first line.

 

What is the best way to move that last line of a text file to be the first line?

 

Please answer the question as asked and don’t suggest making the file be in the correct order when we receive it or changing the automated processing to read the last line first.  Assume those aren’t options.

 

What I came up with was to do tail -1 >newfile and head -<number of lines – 1> but was thinking there ought to be a better way.

 

I see sed can deal with last line, first line and insertion but the examples I’m finding address either/or not moving last line to first line.

 

 

 

 

Athena®, Created for the Cause

Making a Difference in the Fight Against Breast Cancer

 

 

How and Why I Should Support Bottled Water!
Do not relinquish your right to choose bottled water as a healthy alternative to beverages that contain sugar, calories, etc. Your support of bottled water will make a difference! Your signatures count! Go to http://www.bottledwatermatters.org/luv-bottledwater-iframe/dswaters and sign a petition to support your right to always choose bottled water. Help fight federal and state issues, such as bottle deposits (or taxes) and organizations that want to ban the sale of bottled water. Support community curbside recycling programs. Support bottled water as a healthy way to maintain proper hydration. Our goal is 50,000 signatures. Share this petition with your friends and family today!

 

---------------------------------
CONFIDENTIALITY NOTICE: This e-mail may contain privileged or confidential information and is for the sole use of the intended recipient(s). If you are not the intended recipient, any disclosure, copying, distribution, or use of the contents of this information is prohibited and may be unlawful. If you have received this electronic transmission in error, please reply immediately to the sender that you have received the message in error, and delete it. Thank you.
----------------------------------

 

Lightner, Jeff

unread,
Mar 28, 2012, 11:18:42 AM3/28/12
to Atlanta Linux Enthusiasts

I found this works:

awk '{a[NR]=$0} END {print a[NR]; for (i=1;i<NR;i++) print a[i]}' originalfile >newfile

 

Where you replace originalfile and newfile with real file names.

 

 

 


mi...@trausch.us

unread,
Mar 28, 2012, 11:27:50 AM3/28/12
to a...@ale.org
On 03/28/2012 11:10 AM, Lightner, Jeff wrote:
> What is the best way to move that last line of a text file to be the
> first line?

"Best" is subjective...

> Please answer the question as asked and don’t suggest making the file be
> in the correct order when we receive it or changing the automated
> processing to read the last line first. Assume those aren’t options.

k...

> What I came up with was to do tail -1 >newfile and head -<number of
> lines – 1> but was thinking there ought to be a better way.

I would do something similar:

#!/bin/bash
# Put the last line of the file specified into the
# first line of the file specified.

TMP_FILE="$1".$$
tac "$1"|head -n 1 > "${TMP_FILE}"
tac "$1"|tail -n +2|tac >> "${TMP_FILE}"
mv "${TMP_FILE}" "$1"

--- Mike

--
A man who reasons deliberately, manages it better after studying Logic
than he could before, if he is sincere about it and has common sense.
--- Carveth Read, “Logic”

signature.asc

Jim Kinney

unread,
Mar 28, 2012, 11:54:00 AM3/28/12
to Atlanta Linux Enthusiasts
last=$(tail -n 1 file)
first=$(head -n 1 file)
sed -i -e "/$last/d" -e "/$first/ i\
$last
" file

_______________________________________________
Ale mailing list
A...@ale.org
http://mail.ale.org/mailman/listinfo/ale
See JOBS, ANNOUNCE and SCHOOLS lists at
http://mail.ale.org/mailman/listinfo




--
--
James P. Kinney III

As long as the general population is passive, apathetic, diverted to consumerism or hatred of the vulnerable, then the powerful can do as they please, and those who survive will be left to contemplate the outcome.
- 2011 Noam Chomsky

http://heretothereideas.blogspot.com/

Lightner, Jeff

unread,
Mar 28, 2012, 12:02:13 PM3/28/12
to Atlanta Linux Enthusiasts
I wasn't aware of the tac command. It may be all I need as I don't think the order of the other records is important in which case this should work:

tac originalfile >newfile

Thanks.

-----Original Message-----
From: ale-b...@ale.org [mailto:ale-b...@ale.org] On Behalf Of mi...@trausch.us
Sent: Wednesday, March 28, 2012 11:28 AM
To: a...@ale.org
Subject: Re: [ale] Move last line of a file to first line

On 03/28/2012 11:10 AM, Lightner, Jeff wrote:
> What is the best way to move that last line of a text file to be the
> first line?

"Best" is subjective...

> Please answer the question as asked and don't suggest making the file be
> in the correct order when we receive it or changing the automated
> processing to read the last line first. Assume those aren't options.

k...

> What I came up with was to do tail -1 >newfile and head -<number of

> lines - 1> but was thinking there ought to be a better way.

I would do something similar:

#!/bin/bash
# Put the last line of the file specified into the
# first line of the file specified.

TMP_FILE="$1".$$
tac "$1"|head -n 1 > "${TMP_FILE}"
tac "$1"|tail -n +2|tac >> "${TMP_FILE}"
mv "${TMP_FILE}" "$1"

--- Mike

--
A man who reasons deliberately, manages it better after studying Logic
than he could before, if he is sincere about it and has common sense.
--- Carveth Read, "Logic"

Athena(r), Created for the Cause(tm)


Making a Difference in the Fight Against Breast Cancer

---------------------------------


CONFIDENTIALITY NOTICE: This e-mail may contain privileged or confidential information and is for the sole use of the intended recipient(s). If you are not the intended recipient, any disclosure, copying, distribution, or use of the contents of this information is prohibited and may be unlawful. If you have received this electronic transmission in error, please reply immediately to the sender that you have received the message in error, and delete it. Thank you.
----------------------------------

Richard Bronosky

unread,
Mar 28, 2012, 12:41:56 PM3/28/12
to Atlanta Linux Enthusiasts
Be careful doing this with large files. You are storing the whole file
in memory.

I would do this in 2 passes.

# First get the last line into a new file. (assuming the file in
question is passed in as the first argument)
tail -n1 $1 > $1.mod
# Second add the rest of the file, less the last line.
sed '$d' $1 >> $1.mod

This is working with streams. It requires an additional $filesize of
disk space, but it does not require $filesize of RAM.

If you want to be really efficient, use ed. ;-)
# This will trim the last line of the file in place, but I'm not
taking the time to figure out how to add it to the beginning.
ed "$1" << EOF
$
d
w
EOF

Richard Bronosky

unread,
Mar 28, 2012, 1:06:43 PM3/28/12
to Atlanta Linux Enthusiasts
Ooooo! I like this, Jim. But, there is no need for regexing every line
of the doc twice.
file=$1
last=$(tail -n 1 $file)
# if you do this in a chmoded file you have to double the backslash as
I have in the next line
sed -e '$d' -e "1 i\\
$last
" $file

Here it is in downloadable form: https://gist.github.com/2228256

--
.!# RichardBronosky #!.

Jim Kinney

unread,
Mar 28, 2012, 1:27:43 PM3/28/12
to Atlanta Linux Enthusiasts
Cool! Much better. that uses the line number notation to insert before. good shortcut!!

so how about dropping all regex and working the file in line order?


file=$1
last=$(tail -n 1 $file)
sed -i -e "1 i\\
$last
" -e "$ /d" $file

Ed Cashin

unread,
Mar 28, 2012, 9:57:09 PM3/28/12
to Atlanta Linux Enthusiasts
Thanks for mentioning the non-stream editor!  They made sed for streams, because ed is for files.  It is at times like this when I sincerely regret the way distros are beginning to omit ed for the first time in decades.

There's an ed move command called "m".  Move this line to that line.  The one liner below does the same thing as this interactive session

$m0
w
q

ecashin@reynolds:~$ head /etc/passwd | nl > ~/tmp/a
ecashin@reynolds:~$ cp ~/tmp/a ~/tmp/b
ecashin@reynolds:~$ printf '$m0\nw\nq\n' | ed ~/tmp/b
414
414
ecashin@reynolds:~$ diff -u ~/tmp/a ~/tmp/b
--- /home/ecashin/tmp/a 2012-03-28 21:40:25.000000000 -0400
+++ /home/ecashin/tmp/b 2012-03-28 21:41:44.000000000 -0400
@@ -1,3 +1,4 @@
+    10 news:x:9:9:news:/var/spool/news:/bin/sh
      1 root:x:0:0:root:/root:/bin/bash
      2 daemon:x:1:1:daemon:/usr/sbin:/bin/sh
      3 bin:x:2:2:bin:/bin:/bin/sh
@@ -7,4 +8,3 @@
      7 man:x:6:12:man:/var/cache/man:/bin/sh
      8 lp:x:7:7:lp:/var/spool/lpd:/bin/sh
      9 mail:x:8:8:mail:/var/mail:/bin/sh
-    10 news:x:9:9:news:/var/spool/news:/bin/sh
ecashin@reynolds:~$
--
  Ed Cashin <eca...@noserose.net>
  http://noserose.net/e/
  http://www.coraid.com/

Richard Bronosky

unread,
Mar 29, 2012, 12:29:51 AM3/29/12
to Atlanta Linux Enthusiasts
Sadly, I only know "of" ed. But, thanks to you, Ed, I'm now interested
in using ed in my daily workflow. I like this particular use case.
I've added it to my gist.
https://gist.github.com/2228256#file_flop2.sh (I <3 heredoc syntax)

--
.!# RichardBronosky #!.

Jim Kinney

unread,
Mar 29, 2012, 8:09:33 AM3/29/12
to Atlanta Linux Enthusiasts
I must now add ed to my daily tool pile. grep, awk [s]ed, vi[m], bash.

That was a very good "clue bat" on why ed should still be used. a 1M line file would be easy for ed but pain for sed.

Thanks!

On Wed, Mar 28, 2012 at 9:57 PM, Ed Cashin <eca...@noserose.net> wrote:



--

Ed Cashin

unread,
Mar 29, 2012, 8:52:01 AM3/29/12
to Atlanta Linux Enthusiasts
Cool.  I really have to get with the program and put some stuff on github.

Ed Cashin

unread,
Mar 29, 2012, 9:01:04 AM3/29/12
to Atlanta Linux Enthusiasts
Thanks, although it wasn't meant to be a bat.  :)  Because ed is on plan 9, Solaris, Linux, and Mac, out of the box and pretty consistently, I used it as a real interactive editor for a while, after Brantley Coile told me that using it made a difference in the way he thought about his code.

I found it to be a surprisingly useful editor and am fond of it now even though I've gone back to using bigger, less ubiquitous interactive editors.

There's a funny page about ed that y'all might have already seen:

  http://www.gnu.org/fun/jokes/ed.msg

Jim Kinney

unread,
Mar 29, 2012, 9:11:30 AM3/29/12
to Atlanta Linux Enthusiasts
The lines on size were a scream!

Geoffrey Myers

unread,
Mar 30, 2012, 8:42:57 AM3/30/12
to Atlanta Linux Enthusiasts
On 03/29/2012 12:29 AM, Richard Bronosky wrote:
> Sadly, I only know "of" ed. But, thanks to you, Ed, I'm now interested
> in using ed in my daily workflow. I like this particular use case.
> I've added it to my gist.
> https://gist.github.com/2228256#file_flop2.sh (I<3 heredoc syntax)

I used to used ed all the time when I first starting using UNIX. You
can incorporate Ed's ed commands in a here document, stick it in a
script and you have all you need:

cat <<END|ed data
m0
w
q
END


--
Until later, Geoffrey

"I predict future happiness for America if they can prevent
the government from wasting the labors of the people under
the pretense of taking care of them."
- Thomas Jefferson

Reply all
Reply to author
Forward
0 new messages