Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation


by Anonymous Monk
on Oct 28, 2002 at 07:24 UTC ( #208458=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Well, its the usual case of 'this script isnt working and im sure its some silly little error that i just cant notice cause i wrote the script, so i need someone else to look at it and see if they notice anything' type of problem. the script is supposed to be run in a cron job to check the directory one step above itself, see if there are any newly uploaded files, and if so, email someone and alert them. thanks in advance, and sorry to take up yer time :)
#!/usr/bin/perl # Upload Alert Script opendir(DIR,'../'); @dir = readdir(DIR); closedir(DIR); $files = 0; foreach $i (0..$#dir) { if( ($dir[$i] ne "index.html") && ($dir[$i] ne ".") && ($dir[$i] ne "..") && ($dir[$i] ne "cgi-bin") ) {$files = 1} } if($files == 1) { open(MAIL,"|/usr/sbin/sendmail -t"); print MAIL <<"EOC"; To: admin\ From: notify\ Reply-to: admin\ Subject: !!! Newly Uploaded Files !!! New files uploaded. . EOC close(MAIL); }

Comment on STUPID STUPID STUPID old me.
Download Code
by Louis_Wu (Chaplain) on Oct 28, 2002 at 07:43 UTC

    I don't know where the semicolons should be in the 'foreach' block. This is my attempt at 'clear' formatting and placing semicolons correctly.

    foreach $i (0..$#dir) { if( ($dir[$i] ne "index.html") && ($dir[$i] ne ".") && ($dir[$i] ne "..") && ($dir[$i] ne "cgi-bin") ) {$files = 1}; }
    I know that you don't always need a semicolon at the last line of a block, but I don't remember the rules. I'm not sure where to go from here. I'm not even sure that I got the formatting right. :)
      no, the syntax of the script is fine, i ran it through the perl interpreter with the -c flag, the problem has to be something acceptable syntax-wise but bad enough to make the program malfunction.
      its a very very STUPID STUPID STUPID feeling to say the code works fine. Andy
        Yup. After I posted that node, I started playing with all of the provided code, looking at the control blocks, trying to find some error. Then I ran it (using -c to check for errors) and found no problems. {shrug} On to the next node.
by Chady (Priest) on Oct 28, 2002 at 08:09 UTC
    you can start by trying a couple of things:
     1. opendir(DIR,'../') or die "Cannot open dir .. : $!\n"; # maybe you don't have permission or
     2. opendir(DIR, '/full/path/to/dir') or die "Cannot open dir : $!\n";
    3. Tell us what exactly is going wrong.
    He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.

    Chady |
by grantm (Parson) on Oct 28, 2002 at 09:17 UTC
    the script is supposed to be run in a cron job to check the directory one step above itself

    In fact, it checks the directory one step above the current directory of the cron process. If you need the script to start running in a specific directory, then put a 'chdir("/pathname")' at the beginning of the script.

    Alternatively, just open the directory you want to open: opendir("/pathname")

    Or, more simply, don't open it at all - use Perl's glob operator in your loop:

    foreach my $file (</pathname/*>) { if( ($file ne "index.html") && ($file ne ".") && ($file ne "..") && ($file ne "cgi-bin") ) {$files = 1} }

    Also, you might as well break out of the loop once you've set $files to 1 - it's never going to change on subsequent iterations. In fact, you don't really need a loop at all. Try this:

    my @files = grep(!/^(\.\.?|index\.html|cgi-bin)$/, </pathname/*>); if(@files) { # send email }
      forea­ch my $file (</pa­thnam­e/*>) {

      Yuck. Using glob is an excellent idea (I've never seen the utility in opendir()), but for the sake of sanity use the function form instead:

      foreach my $file (glob("/pathname/*")) {

      --Brent Dax
      There is no sig.

by George_Sherston (Vicar) on Oct 28, 2002 at 11:57 UTC
    It's such an obvious point that no sibling monk has yet mentioned it, but if you put
    #!/usr/bin/perl -w use strict;
    at the top of your script you'll get lots of useful diagnostic info, and be prevented from doing anything really dim. See Use strict warnings and diagnostics or die for more info.

    My other thought is that perhaps something is going wrong in your relationship with sendmail. The best way to side step any such problems would be to use a module designed to ease that relationship. I've always had good fortune with Mail::Sendmail.

    § George Sherston
by bart (Canon) on Oct 28, 2002 at 12:27 UTC
    I agree with grantm, you should always use absolute paths in scripts that need to run as a cron job. From what I gather (man crontab), the script is probably invoked from your home directory. A workaround might be to use FindBin to locate the directory the script is in.

    In addition: your code isn't very Perlish. I'll try to Perlify it a bit, mainly by using grep(). Plus, you're only looking for files, not directories, are you? The test can be simplified, that way.

    #!/usr/bin/perl -w use FindBin; chdir("$FindBin::Bin/.."); opendir(DIR, '.'); @dir = readdir(DIR); closedir(DIR); if(my @new = grep {-f and $_ ne "index.html"} @dir) { # send mail... # ... print "New files:\n"; print " * $_\n" foreach @new; }
    I used chdir() because otherwise the filetest won't work.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://208458]
Approved by mce
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (6)
As of 2014-10-25 06:04 GMT
Find Nodes?
    Voting Booth?

    For retirement, I am banking on:

    Results (142 votes), past polls