Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Perl ranges

by merlin's apprentice (Novice)
on May 06, 2013 at 11:16 UTC ( #1032252=perlquestion: print w/replies, xml ) Need Help??

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!!??

Replies are listed 'Best First'.
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; }

    Mike

      Thanks Mike! Let me try that and get back to you with my findings...

        Hi Mike, I tried that this way:

        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?

      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

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!

      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!!??

        What modules did you install and how? What does the code do after the update - does it throw errors and which ones?
        لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

        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 ;)

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"; + } }

    Anne

      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).

        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

        Anne

      Hi Anne, I'd really like for this to only get me those files that have an 'mtime' of between 2013-03-20 and 2013-04-21. How do I get this to do that? PS: I'm very new to perl and taking 'baby' steps at it which is why I'd like your help with this :)

        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:

        1. 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
        2. Look at the month next. Is it bigger, smaller or the same?
        3. Still the same? Check the day next.
        4. 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);

        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"; } } }

        Anne

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;

      I'll first note that <pre> is your friend (but yay, view-source).

      and <code>...</code> is even a better friend. The <code> tag is the tag used here to identify code, data, and output. See also Markup in the Monastery.

      --MidLifeXis

        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?...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1032252]
Approved by greengaroo
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (1)
As of 2022-05-19 03:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you prefer to work remotely?



    Results (71 votes). Check out past polls.

    Notices?