views:

782

answers:

5

I'd like to reverse the lines in a text file (or stdin), preserving the contents of each line.

So, ie, starting with:

foo
bar
baz

I'd like to end up with

baz
bar
foo

Is there a standard unix commandline utility for this?

+11  A: 

Yes:

 tail -r myfile.txt

Reference

Jason Cohen
Wow, never would have guessed tail could do this... Thanks!
Scotty Allen
Just remember that the '-r' option isn't POSIX-compliant. The sed and awk solutions below are going to work even in the wonkiest systems.
guns
+20  A: 

Also worth mentioning: tac (the, ahem, reverse of cat). Part of coreutils.

Mihai Limbășan
Especially worth mentioning to those using a version of tail with no -r option! (Most Linux folks have GNU tail, which has no -r, so we have GNU tac).
oylenshpeegul
Just a note, because people have mentioned tac before, but tac doesn't appear to be installed on OS X. Not that it'd be difficult to write a substitute in Perl, but I don't have the real one.
Chris Lutz
You can get GNU tac for OS X from Fink. You might wish to get GNU tail as well, as it does some things that BSD tail does not.
oylenshpeegul
This also works with cygwin.
bacar
+6  A: 

There's the well-known sed tricks:

# reverse order of lines (emulates "tac")
# bug/feature in HHsed v1.5 causes blank lines to be deleted
sed '1!G;h;$!d'               # method 1
sed -n '1!G;h;$p'             # method 2

(Explanation: prepend non-initial line to hold buffer, swap line and hold buffer, print out line at end)

If you can't remember that,

perl -e 'print reverse <>'

On a system with GNU utilities, the other answers are simpler, but not all the world is GNU/Linux...

ephemient
From the same source:awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file*Both the sed and awk versions work on my busybox router. 'tac' and 'tail -r' do not.
guns
+2  A: 

You can do it using a combination of tail and head :)

file=$1
lineCount=`cat $file | wc -l`
counter=0
while [ $counter -le $lineCount ]
do
    tail -$counter $file | head -1
    counter=`expr $counter + 1`
done
dogbane
+1  A: 

grep -n "" myfile.txt | sort -r -n | gawk -F : "{ print $2 }"

Clever, but hacky:)
Scotty Allen