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

Is there a way to "tail" a file, grabbing a new "last line" the second that it is added? I'm on a win32 and would prefer a no non-standard module solution, if possible.

I know on *nix there is some -T tag on vi or something similar, but how would this be done on Win32?


Replies are listed 'Best First'.
(Ovid) Re: 'Tailing' a File?
by Ovid (Cardinal) on Jan 11, 2001 at 05:14 UTC
    You want something like the following:
    while (1) { while (<FILE>) { # do something here } sleep $for_a_while; seek( FILE, 0, 1 ); }
    The seek above convinces Perl that you're no longer at the EOF, thus allowing you to continuously read from your file as new lines are added.

    However, the real problem is: what's wrong with using a module? If it's reliable and tested, so what?


    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      I used to have to include the unsavory non-standard module disclaimer before i got perl and apache working at home. The sad fact is that many ISPs with Perl/CGI access don't respond favorably to user CPAN requests, and installing modules in non-standard locations can be tricky, especially if there are further non-standard dependencies.

      Take it from someone who tried to install libwww and all dependencies in a user dir :-o

(tye)Re: 'Tailing' a File?
by tye (Sage) on Jan 11, 2001 at 05:14 UTC

    Go read the source code to the File::Tail module, then.

    <sarcasm>Then you can cut-n-paste the code from there and install your copy of it instead of installing the real module (because for some reason installing your own code is not a problem but installing a module is).</sarcasm> (:

            - tye (but my friends call me "Tye")
      Ahhh that old chestnut again.

      While 'rolling your own' is generally accepted as a really dumb thing to do, I think it's a little rough to slap the hand of anybody who even looks like they're reaching for the self constructed apple.

      It's just one of those 'real world' type things that tend to happen. Despite what the rest of the world may be doing, it *might* just be faster, easier and a whole lot easier not to go with a precooked module from CPAN.

      This is not a mini tirade directed at Tye, just an airing of petty groan that seems more and more applicable as the days progress. :)

      What happened to TMTOWTDI? Yeah CPANs great and I'm sure Everything::Cured is just around the corner but do we have to ram it down the throat of every poor sap that asks for advice?

      My advice: Sure give a subtle plug for your pick of CPAN stuff but if the poor soul is requesting advice for a CPAN free solution, try offering a CPAN free solution... even if it is just the same code handcopied across. :)

        Note that my innocent looking smiley was very important. ;) There is no black-and-white to this for me.

        Dealing with CGI forms without using is the closest to an absolute for me. I've never seen a case of not using for CGI forms that wasn't a mistake. Dealing with CGI forms exposed to the world is very complex and getting it wrong has serious consequences.

        Now, a much more middle-of-the-road case is File::Find. There are minor and major problems with File::Find and rolling your own is really pretty easy. Sure, there are several common mistakes that less experienced programmers make again and again when rolling their own File::Find so you should discourage casual re-rolling of File::Find. But I know all of those mistakes and I don't make those when I roll my own. ;)1

        And I understand the way-too-often repeated request for solutions that "use no modules". At one end are modules whose installation involve C compilers, grabbing external libraries from non-Perl web sites, porting code, finding patches, installing other modules that require other modules that require other modules, etc. After you've tried that once, I'm sure you'll be shy about the next time you hear the innocent-sounding "Oh, just install Magic::Black".

        At the other end we have, for example, File::KGlob. Someone once ask how to do what it does without using the module. Well I wrote that crufty old module. It consists of a single file of Perl code. My response then was much like the one I gave above (but without the sarcasm tags and the smiley).

        I suspected that File::Tail is much closer to the File::KGlob end of the spectrum (or I wouldn't have given that flippant response). Well, I just checked, and File::Tail is implemented as a single file of Perl code (but it includes a test suite and example scripts). Unfortunately, it requires the non-standard Time::HiRes and that one includes C code.

        I still suggested that they read the source code for File::Tail as the authors probably bothered to figure out a pretty good way to do things. If I were in this situation I'd probably patch File::Tail so that if Time::HiRes is not installed, then it works around that and just doesn't support sleeping for less than a second (which should be a fine restriction for the vast majority of people).

        When I write modules, I try to be very careful about what modules I require. For example, Win32::TieRegistry has some features that only work if certain modules are installed. But if those modules aren't installed, then everything else works just fine. I wish more module writers were careful about that type of thing.

        1 Recently I needed File::Find functionality and started out using the module. There was a natural way to do what I wanted that just didn't fit well with the way that File::Find did things. I wrote the code to deal with File::Find's different approach and it was awkward. In the end I rolled my own because adding my own traversal code made the rest of the code so much simpler that it was a net win.

                - tye (but my friends call me "Tye")
      I don't have a problem with it. When making a program that'll be used on a multitude of platforms and computers around the world, people tend to avoid it because it requires "more work".

      Its sad, I know, and I'm sure this'll probably get --'ed, but oh well. Thats my explanation :)


        $ vi $ mkdir lib $ mkdir lib/File $ cp /usr/lib/perl5/site_perl/5.6.0/File/ lib/File $ tar cf - . | gzip >my-application-archive.tar.gz
        Unless a module builds itself in an architecture-specific way (note the lack of an architecture-specific directory in the library path), and it's safe to assume the users are all using the same version of Perl (File::Tail goes into 5.6.0, but who knows, it might run fine under 5.005*), copy the library to a local directory and 'use lib' to reference that directory. Now, pack that directory into the archive you use to distribute your application. Viola! You now have a self-contained application that uses non-core Perl modules. I would assume this could easily be adapted for Win32 (using .zip files) as well.

        If you were planning ahead, you would build the modules using your local lib directory ahead of time, and be sure all of the pre-requisites made their way in there as well.

        Is there something inherently wrong with this approach? This is what I always mean when I say it's usually trivial to extend an existing distribution mechanism to include the Perl modules that it needs.

        In addition, if your application is going to be used on a multitude of Perl versions and platforms, carry your package to each of a set of sample systems that it will run on and reinstall your modules. They will all neatly go into their appropriate architecture- and version-specific directories, which will be all-but ignored by architectures and versions that don't use them. Pack the whole thing up again and carry it to your next system, or repeat the process on all of the other Perl versions installed on that system that you'll need.

(tye)Re8: 'Tailing' a File?
by tye (Sage) on Jan 11, 2001 at 10:10 UTC

    Oh, by the way, on Win32 (and only Win32) you can use Win32::ChangeNotify to get told when a new line is added to the file instead of having to periodicly "poll" like you have to on other, inferior (did I say that?), operating systems. ;) At least, the underlying API lets you do that kind of stuff. I think that the Win32::ChangeNotify is well enough written that you can do that same type of thing with the module. {-:

            - tye (but my friends call me "Tye")