lokiloki has asked for the wisdom of the Perl Monks concerning the following question:

There is a file of unknown length. I want to read X bytes from the end of that file. Here is my script:

$bytes = 100000; open (FILE, 'somefile.data'); seek (FILE, -$bytes, 2); while (<FILE>) { print $_; } close FILE;
This works perfectly fine on most of the machines I try it on. However, it does NOT work on SOME machines where $bytes is greater than the size of the file. I.e., if the file is 10kb and I ask to read the last 100kb it returns "nothing" on some servers, while on others it works.

I tried to add the following, thinking that the aforementioned seek would return "false" on those machines:

seek (FILE, 0, 1) unless seek (FILE, -$bytes,2);

This didn't do anything. The same problem is occuring when I try to seek with a too large byte offset.

Can someone help?

Thanks...

Replies are listed 'Best First'.
Re: problem using seek on some systems
by ikegami (Patriarch) on Dec 06, 2006 at 21:47 UTC

    How about

    my $seek_loc = (-s FILE) - $bytes; $seek_loc = 0 if $seek_loc < 0; seek(FILE, $seek_loc, 0);

    By the way, you should use lexical variables and 3-arg open whenever possible.

    open(my $fh, '<', $file_name) or die("Unable to read log file \"$file_name\": $!\n");

      There is no guarantee that -s and seek use identical values. On Unix, that is usually the case. Other places, not as much. If you want to get the seek position of the end of the file (portably), use seek then tell.

      - tye        

        Could you give us an example of when this might not be the case?

        Is this a units thing? unicode -v- bytes. Or a platform line ending thing?

      thank you very much sir. what's the benefit of using lexical variables and 3-arg opens over the old way of doing things?

        Lexical variables have a tighter scope than package variables. There are numerous advantages to limiting the scope of a variable. Predominantly, your handle will be closed if even if you don't execute the block to its end.

        Reasons not to use a lexical variable for a file handle: Supporting Perl versions older than 5.6.0.

        The 3-arg open can open files 2-arg open can't open. The 3-arg open is not subject to the injection bugs and attacks to which 2-arg open is vulnerable.

        Reasons not to 3-arg open. Wanting to open STDIN/STDOUT using '-'. Wanting to work file descriptors. Wanting to open a pipe.

Re: problem using seek on some systems
by swampyankee (Parson) on Dec 06, 2006 at 21:58 UTC

    One possibility would be to use -s to get the file size, and set $bytes from that. Another is to try File::ReadBackwards.

    emc

    At that time [1909] the chief engineer was almost always the chief test pilot as well. That had the fortunate result of eliminating poor engineering early in aviation.

    —Igor Sikorsky, reported in AOPA Pilot magazine February 2003.