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

I hope I can outline this clearly the first time. I have been asked to create a script to do the following:
  1. Search a series of Directories that have been created withing 15 minutes of the current system time for a dynamic file name that ends in (dot)out .out.
  2. If a file with that extension is found, search the file for the word "error".
  3. If error is found, send an email to a data center operator.
  4. If the word is NOT found, do nothing.
I believe I can handle items 3 and 4, but I am looking for help and suggestions in accomplishing item 1. Thanks in Advance.

Replies are listed 'Best First'.
Re: File Search
by broquaint (Abbot) on Oct 22, 2003 at 23:16 UTC
    A more programmatic solution to finding the appropriate files can be found through using File::Find::Rule
    use File::Find::Rule my $rule = rule( file => name => '*.out', grep => qr/error/, start => \@directory_list, ); while(my $file = $rule->match) { # send mail here }
    See. the File::Find::Rule docs for more information on this most marvellous of modules.
    HTH

    _________
    broquaint

Re: File Search
by Beechbone (Friar) on Oct 22, 2003 at 21:15 UTC
    Ok, the shell solutions are good, but if you really want to use Perl have a look on this:
    use File::Find; find(\&wanted, './'); sub wanted { return unless /\.out$/; open F, '<', $_ or return; while (defined (my $line = <F>)) { print "ACTION!" if $line =~ /error/; } close F; }
    #1 => File::Find is the module for searching a directory tree. Have a look at the POD to find out more.

    #2 => If the files are big, you may want to think about optimizing, but for small files above is enough.

    #3 => There are multiple modules on CPAN to do this cleanly. Search for sendmal or smtp and choose what fits your needs.

    #4 => That's hard. You may want to look for a module like ACME::NOP or CORE::return, but I'm really unsure if they do enough nothing... ;-))


    Update: And don't try to look at a Perl Monks Preview after to much Irish Coffee---you won't see the missing <p>s...

    Search, Ask, Know
      Thanks for guidenance. I have it working in my test environment. However, I know in my production environment I will be encountering files and directories from previous process runs. I need to be able to only select those directories/Files that have been created on the current date, and if possible between a defined start and end time. Any suggestions? Thanks in Advance.
        That's fairly easy. Just see perldoc -f stat. You can get all possible data about a file, including the last change timestamp.

        Please note, you cannot usually get the creation time, because it is not recorded by all file/operating systems.

        sub wanted { return unless /\.out$/; my $ctime = (stat $_)[9]; if ($ctime < time()-(2*60*60)) { print "$_ is older than 2 hours.\n"; } elsif ($ctime > time()) { print "$_ has used a time machine to get here!\n"; } else { un#link $_; print "I hate new files.\n"; } }

        Search, Ask, Know
Re: File Search
by dragonchild (Archbishop) on Oct 22, 2003 at 16:01 UTC
    Assuming you're on some Unix-based system:
    #!/bin/sh for file in $(find . -name '*.out' | xargs grep -n error) do mail "$file has an error in it!" -m operator@my.datacenter.org done

    A similar script can be written using the Windows script language, as well.

    In other words, you don't need Perl for this.

    ------
    We are the carpenters and bricklayers of the Information Age.

    The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

    ... strings and arrays will suffice. As they are easily available as native data types in any sane language, ... - blokhead, speaking on evolutionary algorithms

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      Eep! At least assign all the files/output of find to an array and send 1 email :)

      Play that funky music white boy..
      ...obviously I'm lost.

      I thought that this was the "How_To_Avoid_Using_Perl Monks" web site!

      ...All the world looks like -well- all the world, when your hammer is Perl.
      ---v

        Just because you can do something in Perl doesn't mean you should do it in Perl. Shell scripting is a very valuable tool that is the best tool for a certain set of specific tasks, such as dealing with the Unix filesystem in simple ways.

        ------
        We are the carpenters and bricklayers of the Information Age.

        The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

        ... strings and arrays will suffice. As they are easily available as native data types in any sane language, ... - blokhead, speaking on evolutionary algorithms

        Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: File Search
by Abigail-II (Bishop) on Oct 22, 2003 at 16:16 UTC
    That might be impossible to do on a Unix system, because Unix does not keep track of creation times of file or directories. "Creation time" is ambiguous. Assuming that 'foo' exists, and 'bar' doesn't, does "mv foo bar" create bar?

    But assuming you know the directories to search by some divine means, no need for Perl. Something like the following will do:

    $ find dir1 dir2 dir2 -name '*.out' \ '!' -exec grep -q error {} ';' \ -exec sh -c 'echo "Whatever" | mail you@there.fo +o' ';'

    Abigail

      ...isn't that a little bit literal-minded?

      In my reading of the problem, I concluded that the creation time was also the likely most-recent modification time. Especially in the subsequent clarification of the problem statement, it seemed clear to me (although not necessarily true) that the issue was to avoid analyzing files from previous runs of the procedure. In such a case both the mod time and the inode-change time of old files are likely to have been unchanged during the most recent program run.

      I'm all for clarifying that ctime is not the "creation time" but the initial statement here, "That might be impossible to do on a Unix system" really caught me by surprise. Had it not come from a credible source, I would likely have ignored the remainder of the message.

      ...All the world looks like -well- all the world, when your hammer is Perl.
      ---v

Re: File Search
by Aragorn (Curate) on Oct 22, 2003 at 21:26 UTC
    This is the Perlmonks, so we'll do a version in Perl (not thoroughly tested):
    use strict; use warnings; use File::Find; use Mail::Send; my $curtime = time(); find(\&wanted, qw(/home/arjen/test)); sub wanted { # Warning: the ctime field is not really the creation time! # See perlport (File and Filesystems) return if (($curtime - (stat($File::Find::dir))[10])) > 900; return if $_ !~ /\.out$/; open(FILE, "<$_") or die "Cannot open $_: $!\n"; while (my $line = <FILE>) { last if $line =~ /error/; } close(FILE); my $msg = Mail::Send->new(Subject => "Error found!", To => "operator\@datacenter"); my $fh = $msg->open(); print $fh "We found an error in $_!\n"; $fh->close(); print "Mail sent\n"; }

    Arjen

      I am using a subset of your suggestion, but am getting an error when trying to open the file to read it.
      use File::Find; find(\&wanted, '/opt/psoft/hr83tst/appserv/prcs/HRTST/log_output/'); print $_ ; sub wanted { return unless /\.out$/; open F, $_ or return ; while (defined (my $line = <F>)) { if (-M $_ < 0.5) { print $_ if $line =~ /error/ ; system("mail -s' $_' mikev\@beverlycorp.com<$line"); return; } } close F; }
      This is teh error being returned - "A file or directory in the path name does not exist. sh: error: 0403-016 Cannot find or open the file." Any help is greatly appreciated.
        sh: error: 0403-016 Cannot find or open the file
        It looks like the system command goes wrong, or more specifically, the shell which is started by system can't start the mail program. Is the directory where mail is located in your PATH? Does the mail program even exist?

        Arjen