This is what my Perl code looks like for monitoring a Unix folder :
#!/usr/bin/perl
use strict;
use warnings;
use File::Spec::Functions;
my $date = `date`; chomp $date;
my $datef = `date +%Y%m%d%H%M.%S`; chomp $datef;
my $pwd = `pwd`; chomp $pwd;
my $cache = catfile($pwd, "cache");
my $monitor = catfile($pwd, "monme");
my $subject = '...';
my $msg = "...";
my $sendto = '...';
my $owner = '...';
sub touchandmail {
`touch $cache -t "$datef"`;
`echo "$msg" | mail -s "$subject" $owner -c $sendto`;
}
while(1) {
$date = `date`; chomp $date;
$datef = `date +%Y%m%d%H%M.%S`; chomp $datef;
if (! -e "$cache") {
touchandmail();
} elsif ("`find $monitor -newer $cache`" ne "") {
touchandmail();
}
sleep 300;
}
To do a
chomp
after every assignment does not look good. Is there some way to do an "autochomp"?I am new to Perl and might not have written this code in the best way. Any suggestions for improving the code are welcome.
It is possible to assign and
chomp
in a single line using the following syntax:As for speaking more Perlishly, if you find yourself repeating the same thing over and over again, roll it into a sub:
More generally, the
IO::All
module does indeed provide the equivalent of an autochomp:or more generally:
Granted, for this particular case of
date
I would agree with the other answerers that you are probably better off using one of the DateTime modules, but if you are simply reading in a file and want all your lines to bechomp
ed, thenIO::All
with thechomp
andtie
options applied is very convenient.Note also that the
chomp
trick doesn't work when slurping the entire contents of the handle into a scalar directly (that's just the way it is implemented).Use DateTime or other of the date modules on CPAN instead of the date utility.
For example:
Don't use the shell, then.
The result is slightly different: the output of the
date
command contains a timezone, but the value of$date
above will not. If this is a problem, follow the excellent suggestion by Chas. Owens below and usestrftime
to get the format you want.Your sub
will fail silently if something goes wrong. Silent failures are nasty. Better would be code along the lines of
Using
system
rather than backticks is more expressive of your intent because backticks are for capturing output. Thesystem(LIST)
form bypasses the shell and having to worry about quoting arguments.Getting the effect of the shell pipeline
echo ... | mail ...
without the shell means we have to do a bit of the plumbing work ourselves, but the benefit—as withsystem(LIST)
—is not having to worry about shell quoting. The code above uses many-argumentopen
:The
open
above forks amail
process, and$fh
is connected to its standard input. The parent process (the code still runningtouchandmail
) performs the role ofecho
withprint $fh $msg
. Callingclose
flushes the handle's I/O buffers plus a little extra because of how we opened it:Try putting it into a function:
And then call that for each command you want to execute and then chomp.