Output file lines from last to first in Bash
Asked Answered
V

6

41

I want to display the last 10 lines of my log file, starting with the last line- like a normal log reader. I thought this would be a variation of the tail command, but I can't find this anywhere.

Vivianviviana answered 5/11, 2011 at 1:16 Comment(1)
you mean starting from the last line, then last line -1, last line -2 etc...?Gq
V
8

I ended up using tail -r, which worked on my OSX (tac doesn't)

tail -r -n10
Vivianviviana answered 6/11, 2011 at 20:30 Comment(3)
This is the best answer because it is not GNU specific and avoids a "useless use of cat". smallo.ruhr.de/award.htmlSupernova
Does not work root@elk:/# tail -r -n1 /var/log/logstash-test-output.log tail: invalid option -- 'r'Sweetscented
@KarlMorrison This won't work for non-BSD tail commands. See my answer for more help...Gaskin
G
58

GNU (Linux) uses the following:

tail -n 10 <logfile> | tac

tail -n 10 <logfile> prints out the last 10 lines of the log file and tac (cat spelled backwards) reverses the order.

BSD (OS X) of tail uses the -r option:

tail -r -n 10 <logfile>

For both cases, you can try the following:

if hash tac 2>/dev/null; then tail -n 10 <logfile> | tac; else tail -n 10 -r <logfile>; fi

NOTE: The GNU manual states that the BSD -r option "can only reverse files that are at most as large as its buffer, which is typically 32 KiB" and that tac is more reliable. If buffer size is a problem and you cannot use tac, you may want to consider using @ata's answer which writes the functionality in bash.

Gaskin answered 5/11, 2011 at 1:21 Comment(6)
I'm sure this is right, but looks like the 'tac' command doesn't exist on OSX shell...Vivianviviana
@Vivianviviana See #742966 for some alternatives to tac, not all of which are portable.Grethel
Sorry, I have to ding you for "useless use of cat" smallo.ruhr.de/award.html since tail has the option -r to reverse the order. So tail -r -n 10 <logfile> is the better choice. As a bonus tail -r works on non-GNU systems like OSX, Solaris, AIX, etc.Supernova
@RichardBronosky Nice link, I've edited my answer to also include the -r option.Gaskin
@RickSmith respectable humility, friend. I received the award in 1999 and have been diligent ever since. Also, I was GNU-only from 1995-1999 before getting plunged into Posix systems and had to relearn a lot because the admins refused to install all the sugar I was used to.Supernova
GNU tail does not have the -r option, see gnu.org/software/coreutils/manual/html_node/…Naima
A
16

tac does what you want. It's the reverse of cat.

tail -10 logfile | tac

Augustineaugustinian answered 5/11, 2011 at 1:22 Comment(0)
V
8

I ended up using tail -r, which worked on my OSX (tac doesn't)

tail -r -n10
Vivianviviana answered 6/11, 2011 at 20:30 Comment(3)
This is the best answer because it is not GNU specific and avoids a "useless use of cat". smallo.ruhr.de/award.htmlSupernova
Does not work root@elk:/# tail -r -n1 /var/log/logstash-test-output.log tail: invalid option -- 'r'Sweetscented
@KarlMorrison This won't work for non-BSD tail commands. See my answer for more help...Gaskin
F
3

You can do that with pure bash:

#!/bin/bash
readarray file
lines=$(( ${#file[@]} - 1 ))
for (( line=$lines, i=${1:-$lines}; (( line >= 0 && i > 0 )); line--, i-- )); do
    echo -ne "${file[$line]}"
done

./tailtac 10 < somefile

./tailtac -10 < somefile

./tailtac 100000 < somefile

./tailtac < somefile

Fenella answered 5/11, 2011 at 13:34 Comment(0)
Z
2

This is the perfect methods to print output in reverse order

tail -n 10 <logfile>  | tac
Zigzagger answered 2/7, 2014 at 9:24 Comment(2)
What are the asterisks for?Vivianviviana
Including the word "perfect" is just inviting criticism.Supernova
P
0

Pure bash solution is

_tac_echo() {
  IFS=$'\n'
  echo "${BASH_ARGV[*]}"
}

_tac () {
  local -a lines
  readarray -t lines
  shopt -s extdebug
  _tac_echo "${lines[@]}"
  shopt -u extdebug
}

cat <<'EOF' | _tac
1 one line[of] smth
2 two line{of} smth
3 three line(of) smth
4 four line&of smth
EOF

which prints

4 four line&of smth
3 three line(of) smth
2 two line{of} smth
1 one line[of] smth
Prasad answered 19/10, 2023 at 8:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.