gnu@perl has asked for the wisdom of the Perl Monks concerning the following question:

What is the best way to tail a file using only perl, no shell / system commands?

I have already done this:

open(FILE,'/var/adm/messages'); my @arr = (<FILE>); print reverse(@arr);

This works, but I am kind of concerned about loading a HUGE file into @arr. So I tried this:

open(FILE,'/var/adm/messages'); print reverse(<FILE>);

In the actual 'print' segments I would use a counter to limit the lines printed to the number requested.

What other way would you recommend to get a 'tail' of a file.

TIA, Chad.

Replies are listed 'Best First'.
Re: tail a file in perl
by broquaint (Abbot) on Oct 23, 2002 at 14:19 UTC
Re: tail a file in perl
by jwest (Friar) on Oct 23, 2002 at 14:33 UTC
    If you don't particularly feel the need to roll your own, File::Tail is a nice way to do it. Reduce, reuse, recycle and all that.

    --jwest

    update: I assumed, possibly mistakenly, that the poster wanted something like 'tail -f' instead of vanilla 'tail'.
    -><- -><- -><- -><- -><-
    All things are Perfect
        To every last Flaw
        And bound in accord
             With Eris's Law
     - HBT; The Book of Advice, 1:7
    
Re: tail a file in perl
by roik (Scribe) on Oct 23, 2002 at 14:18 UTC
    I don't know if you have read it, but perlfaq5 has a section called "How do I do a tail -f in perl?"
Re: tail a file in perl
by SarahM (Monk) on Oct 23, 2002 at 14:25 UTC
    Here is a piece of code that I've written to get the last lines in a file for one of my programs:
    my @lines; my $currLine = 0; my $maxLines = 10; # Go through the file, saving the last $maxLines while (<>){ $lines[$currLine] = $_; $currLine++; $currLine = 0 if ($currLine == $maxLines); } # Print out the last $maxLines for (1..$maxLines){ print $lines[$currLine]; $currLine++; $currLine = 0 if ($currLine == $maxLines); }
    I think this code is simple enough to understand what is going on, but if you need to explain more I will. (I have to get some real work done first ;)
      Or a slightly more Perl-flavored version of your C-flavored code:
      my @lines; my $maxlines = 10; while (<>) { push @lines, $_; shift @lines if (@lines > $maxlines); } print join("\n", @lines) . "\n";
      Instead of using a circular array, this uses @lines as a FIFO buffer, storing the last $maxlines lines, using push and shift. Much less code! I'm not sure if this is the way it's implemented in the aforementioned perlfaq5 and other discussions...

      Update: The solutions here using seek to read blocks starting at the end are going to be more efficient than this one (as the whole file is not read), although this solution is fine for reasonable-sized files.. Plus I think it's much simpler to comprehend.

      blokhead

Re: tail a file in perl
by Jaap (Curate) on Oct 23, 2002 at 15:25 UTC
    Slightly off topic but nonetheless interesting: If you want the last 100 bytes of a file, this is VERY fast (and scales beautifully for very large files):
    #!/usr/bin/perl -w use strict; if (open (FH, $ARGV[0])) { seek FH, -100, 2; while (<FH>) { print $_; } close (FH); }