Skip to content

Print lines in reverse order

On a popular Linux magazine, one of the writers asked people to come up with different ways to print the lines of a file in reverse order, ie like what the program tac does.

So here are some ways to do that, almost all of which are silly, useless, crazy, dangerous and inefficient. You have been warned.

Some can work with both standard input and a real file, some only work with a real file (the examples all use a file). The shell examples use some bash-specific features for convenience, although they could all be rewritten to use only standard constructs (except the one that uses arrays).

No explanations to avoid spoiling the fun (some are obvious though).

tac file
cat -n file | sort -k1,1rn | cut -f 2-
awk '{a[NR]=$0} END {for(i=NR;i>0;i--)print a[i]}' file
perl -e 'print reverse <>' file
perl -ne 'push @a,$_; print reverse @a if eof' file
sed '1!G;h;$!d' file
awk '{out = $0 s out; s = RS} END {print out}' file
while IFS= read -r arr[i]; do ((i++)); done < file
for((j=i-1;j>=0;j--)); do printf "%s\n" "${arr[$j]}"; done
sed ':a;$!{N;ba;}; s/$/\x1/; 
     :b; s/\n\{0,1\}\([^\n]*\)\x1\(.*\)/\x1\2\n\1/; /^\x1/!bb; 
     s/\x1\n//' file
while true; do
  if gawk -v n="$i" 'NR==n{exit}END{print;exit NR-1}' file; then
# NEVER do this
touch outfile
while IFS= read -r line; do
  { rm outfile; { printf "%s\n" "$line"; cat; } > outfile; } < outfile
done < file
cat outfile
rm outfile
while IFS= read -r line; do
  printf "%s\n" "$line" > "$i".txt
done < file

while [ $i -gt 0 ]; do
  cat $i.txt

rm *.txt
# same idea as above, unnecessarily extra-complicated...
shift_names() {
  while [ $n -gt 0 ]; do
    mv "$n.txt" "$((n+1)).txt"

while IFS= read -r line; do
  shift_names $i
  printf "%s\n" "$line" > 1.txt
done < file

for((j=1;j<=i;j++)); do
  cat $j.txt

rm *.txt
printf '<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="">

recode utf8..xml < file | sed = | sed 'N;s/\n/ /' | awk -v ORS='&#xa;' 1

printf '</a:value>
} | curl -s -o - -d @- \
-H 'Content-Type: application/soap+xml;charset=utf-8' \
-H 'SOAPAction: ""' \
'' |\
xmlstarlet sel -T -t -v '//sortReturn' | perl -pe 's/^\d+ //'

If you can think of other ways (for example based on different ideas, more convoluted, or using other programming languages, etc.) contributions are welcome.

Update 02/01/2011 - here's another one:

LC_ALL=C awk -v x="0" '{y += length($0) + 1; x = y RS y FS x}END{print substr(x, index(x, RS) + 1)}' file | \
while IFS=" " read -r a b; do
  dd skip=$b count=$((a - b)) bs=1 2>/dev/null < file

One Comment

  1. shantiq says:

    Thanx amazing

    tac and perl work a treat

    Downloaded Messages in FB Data which gives you a file called messages.htm in reverse chronological order ... this cures that in under a second ... copy section you want sve as .txt and badaboom