merlin's apprentice has asked for the wisdom of the Perl Monks concerning the following question:
Hello all,
Remember that problem you'd helped me solve earlier?
Well, I had to update the system and I think the perl on it broke :(
I've tried downloading and installing all modules mentioned here but the thing seems to be laughing in my face!!
Here's the code that we fixed that time.
Please tell me what Perl modules to install on perl-5.16.2_1 to make this work?
use strict;
use warnings;
use Net::FTP;
use File::Listing qw(parse_dir);
use POSIX qw(strftime);
my ($host, $user, $passwd) = ('1.2.3.4', 'abcd', 'efgh');
my $dir = '/abc/def/ghi';
my $ftp = Net::FTP->new($host)
or die qq{Cannot connect to $host: $@};
$ftp->login($user, $passwd)
or die qq{Cannot login: }, $ftp->message;
$ftp->cwd($dir)
or die qq{Cannot cwd to $dir: }, $ftp->message;
my $ls = $ftp->dir();
$ftp->binary();
foreach my $entry (parse_dir($ls)) {
my ($name, $type, $size, $mtime, $mode) = @$entry;
next unless $type eq 'f';
my $time_string = strftime "%Y-%m-%d", gmtime($mtime);
if ($time_string ge '2013-03-21' && $time_string le '2013-04-2
+0') {
print "File $name has an mtime of $time_string\n";
$ftp->get($name)
or die "get failed ", $ftp->message;
}
}
$ftp->quit;
It was getting files from the 21st to the 31st of the month and working fine till I updated the Perl and broke it :(
The reason I want it this way is so that someone who isn't very familiar with scripts can easily modify the dates and away they'd go!
How do I fix this 'broken' Perl and make the above code (previously working) work again!!??
Re: Perl ranges
by RMGir (Prior) on May 06, 2013 at 11:46 UTC
|
TMTOWTDI :)
But the easiest would seem to me to be a regular expression (assuming you mean files from the 21st to the 31st in the $time_string field?):
if ($time_string =~ /\d\d\d\d-\d\d-(\d\d)/ && ($1>=21 && $1<=31))
+{
print "File $name has an mtime of $time_string\n";
$ftp->get($name)
or die "get failed ", $ftp->message;
}
| [reply] [d/l] |
|
| [reply] |
|
my $time_string = strftime "%Y-%m-%d", gmtime($mtime);
if ($time_string =~ 2013-04-01 && ($1>=01 && $1<=20)) {
print "File $name has an mtime of $time_string\n";
$ftp->get($name)
or die "get failed ", $ftp->message;
And it still didn't work for me.
You see, what I'd like for it to do is change the day only incrementally from the 1st of the month to the 20th of the month (as in the example above)
Is there any way I could do that using your code?
| [reply] [d/l] |
|
Hi Mike,
I've tried it this way:
if ($time_string =~ /\2013-\04-(\01)/ && ($1>=01 && $1<=20))
{
print "File $name has an mtime of $time_string\n";
$ftp->get($name)
or die "get failed ", $ftp->message;
It hasn't brought any results -just returned the prompt
| [reply] [d/l] |
Re: Perl ranges
by merlin's apprentice (Novice) on May 06, 2013 at 14:55 UTC
|
Hello all,
I've fixed it!!
my $time_string = strftime "%Y-%m-%d", gmtime($mtime);
if ($time_string gt '2013-03-21' && $time_string lt '2013-04-20')
+{
print "File $name has an mtime of $time_string\n";
$ftp->get($name)
or die "get failed ", $ftp->message;
Thanks for trying to help out a new member and I hope we work together forever!
Thank you all!
| [reply] [d/l] |
|
Hello all,
Remember that problem you'd helped me solve earlier?
Well, I had to update the system and I think the Perl on it broke :(
I've tried downloading and installing all modules mentioned here but the thing seems to be laughing in my face!!
Here's the code that we fixed that time.
Please tell me what Perl modules to install on perl-5.16.2_1 to make this work?
use strict;
use warnings;
use Net::FTP;
use File::Listing qw(parse_dir);
use POSIX qw(strftime);
my ($host, $user, $passwd) = ('1.2.3.4', 'abcd', 'efgh');
my $dir = '/abc/def/ghi';
my $ftp = Net::FTP->new($host)
or die qq{Cannot connect to $host: $@};
$ftp->login($user, $passwd)
or die qq{Cannot login: }, $ftp->message;
$ftp->cwd($dir)
or die qq{Cannot cwd to $dir: }, $ftp->message;
my $ls = $ftp->dir();
$ftp->binary();
foreach my $entry (parse_dir($ls)) {
my ($name, $type, $size, $mtime, $mode) = @$entry;
next unless $type eq 'f';
my $time_string = strftime "%Y-%m-%d", gmtime($mtime);
if ($time_string ge '2013-03-21' && $time_string le '2013-04-2
+0') {
print "File $name has an mtime of $time_string\n";
$ftp->get($name)
or die "get failed ", $ftp->message;
}
}
$ftp->quit;
It was getting files from the 21st to the 31st of the month and working fine till I updated the Perl and broke it :(
The reason I want it this way is so that someone who isn't very familiar with scripts can easily modify the dates and away they'd go!
How do I fix this 'broken' Perl and make the above code (previously working) work again!!?? | [reply] [d/l] |
|
What modules did you install and how? What does the code do after the update - does it throw errors and which ones?
| [reply] |
|
|
|
|
|
I fixed it!! :D
I found the missing module and installed it! :)
Again, thank you all for your help!
Every day I learn something on perl ;)
| [reply] |
Re: Perl ranges
by Anneq (Vicar) on May 06, 2013 at 12:51 UTC
|
foreach (@array_of_filenames) {
my $mtime = (stat($_))[9]; # Get mtime for file
my $month = (localtime($mtime))[4] +1; # Get month for file
my $day = (localtime($mtime))[3]; # Get day of month for file
my $thismtime = (stat())[9]; # Get mtime for today
my $thismonth = (localtime())[4] +1; # Get this month
if ($month == $thismonth and $day >= 21) { print "Filename: $_\n";
+ }
}
| [reply] [d/l] |
|
stat does not stat files over FTP. You can use the Net::FTP mdtm method to get the files mtime (supposed to be UTC which may not match the date/time you see in a dir listing).
| [reply] |
|
Good catch, runrig. I only tested my code snippet locally and it didn't occur to me that I was using localtime() locally, even though the file stat info would be from another host. I'm too used to relying on my ssh configs and the command line to do things like that:
$ ssh somedomain.com somecommand
Running stat on the remote host would give me the remote localtime. But that's not what the OP is doing.
Thanks
| [reply] [d/l] |
|
| [reply] |
|
New to programming in general I take it?
Often the thing to do is ask yourself "how do you do it manually?", and then have the computer do it the same way. There are usually tricks, standard algorithms and modules to do it, but at the core of it all is figuring out what steps need to be followed to accomplish a goal.
How do you compare two dates manually? Myself, I do:
- Look at the year first. Is it bigger, smaller or the same? If it is smaller or bigger, then you're done. Otherwise, go to step 2
- Look at the month next. Is it bigger, smaller or the same?
- Still the same? Check the day next.
- Still the same? Then the dates are the same.
A convenient operator for this sort of sequence in general is <=> it returns -1, 0 or +1 depending on whether the left side is smaller,equal, or bigger than the right side. Combine that with or, which will return the left side if it is true, otherwise return the right side. (Standard boolean logic: false or true => true, false or false => false, true or anything => true)
my $result = $startRange eq 'any' or $year <=> $startRangeYear or $month <=> $startRangeMonth or $day <=> $startRangeDay;
Dates in particular have a nice property that lets you compare them even easier. Write the date as a number with zero padding: 20130506 and compare it to some other date given the same treatment: 20121225. Now it is trivial to see if one date is less than, equal or greater than another. my $ymd = sprintf('%04d%02d%02d', $year, $month, $day);
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
|
Welcome to perl!
Stick with it. It is useful for so many things and there is help to be had in many places.
I've provided you with some code for tutorial purposes but I'd recommend going with Mikes because it is more elegant and versatile.
The script below works on files in the current directory containing the perl script.
For information on $|, visit Suffering from Buffering. It basically makes sure your output comes out as expected.
For more information on perl, such as the localtime() and stat(), functions, checkout perl.org and your local ActiveState documentation and, of course, Google is your friend.
use strict;
use warnings;
$|=1; # Buffering
my @filenames;
opendir DIR, "." or die "Failed while trying to open current directory
+\nPerl says: \n$!";
@filenames = readdir DIR; # Get list of files in current directory
shift @filenames; shift @filenames; # remove . and ..
foreach (@filenames) {
my $mtime = (stat($_))[9]; # Get mtime for file
my $year = (localtime($mtime))[5] + 1900; # Get year for file
my $month = (localtime($mtime))[4] +1; # Get month for file
my $day = (localtime($mtime))[3]; # Get day of month for file
if ($month >= 03 and $year == "2013") {
if ($month == 03 and $day >=20) { print "Filename: $_\n"; }
if ($month == 04 and $day <=21) { print "Filename: $_\n"; }
}
}
The code to drop in your script might be: (Warning: Not tested)
my @filenames = parse_dir($ls);
foreach (@filenames) {
my $mtime = (stat($_))[9]; # Get mtime for file
my $year = (localtime($mtime))[5] + 1900; # Get year for file
my $month = (localtime($mtime))[4] +1; # Get month for file
my $day = (localtime($mtime))[3]; # Get day of month for file
if ($month >= 03 and $year == "2013") {
if ($month == 03 and $day >=20) { print "Filename: $_\n"; }
if ($month == 04 and $day <=21) { print "Filename: $_\n"; }
}
}
| [reply] [d/l] [select] |
|
|
Re: Perl ranges
by wrog (Friar) on May 06, 2013 at 12:08 UTC
|
I'll first note that <pre> is your friend (but yay, view-source).
$time_string =~ m/^2013-03-[23][0-9]/
would be one way to do it. Though I think I might prefer
my (undef,undef,undef,$mday,$mon,$year)=gmtime($mtime);
if ($year == 2013 && $mon+1 == 3 && 21 <= $mday)
It's a hard call, what with having to deal with zero-based $mon
Original code below:
use strict;
use warnings;
use Net::FTP;
use Time::Local;
use File::Listing qw(parse_dir);
use POSIX qw(strftime);
my ($host, $user, $passwd) = ('xxx.xxx.xxx.xxx', 'abc', 'abc');
my $dir = '/abc/def/ghi';
my $ftp = Net::FTP->new($host)
or die qq{Cannot connect to $host: $@};
$ftp->login($user, $passwd)
or die qq{Cannot login: }, $ftp->message;
$ftp->cwd($dir)
or die qq{Cannot cwd to $dir: }, $ftp->message;
my $ls = $ftp->dir();
$ftp->binary();
foreach my $entry (parse_dir($ls)) {
my ($name, $type, $size, $mtime, $mode) = @$entry;
next unless $type eq 'f';
my $time_string = strftime "%Y-%m-%d", gmtime($mtime);
if ($time_string eq '2013-03-29') {
print "File $name has an mtime of $time_string\n";
$ftp->get($name)
or die "get failed ", $ftp->message;
}
}
$ftp->quit;
| [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
|
oh, all right...
I don't suppose there's any way to turn off having download links appear for two-line snippets.
Oh, wait, there is! Who knew?...
| [reply] |
|
|