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

hi
need really HELP to change this perl script.
this perl script opens and reads the info file, renames the first file, sends via ftp the first file,
waits 20 minutes, renames the second file and sends via ftp.
all files are text files.
the problem is, it sends files to the same directory.
how to change it, to send the second file to the different directory?
for example to:
"FTP/B2" ?
#!/usr/bin/perl -w use strict; use warnings; use Net::FTP; # change directory chdir "/ftp/files" or die "/ftp/files: $!\n"; # DO NOT transfer without info file -f "/ftp/files/info" or die "info file is missing\n"; open(FILE, "<info>"); while (<FILE> ) { s/\W*$//; next if (!$_); /^(.+?) \s+ (.+?)$/x; my ($old, $new) = ($1, $2); rename $old, $new; # ftp transfer my $server = "X.X.X.X"; my $ftp = Net::FTP->new ($server, Timeout => 9000, Debug => 3); $ftp or die "$server: cannot connect: $@"; # If you don't use ~/.netrc $ftp->login ('anonymous', 'mail@adress') or die "$_: cannot logon: " . $ftp->message; # change remote directory for the first file $ftp->cwd("FTP/A1"); # Put first file to the ftp server $ftp->put ($2) or die "$server: cannot put $2: " . $ftp->message; sleep (20 * 60) }
kind regards
cc

jdporter - retitled

Replies are listed 'Best First'.
Re: Problem using Net::FTP
by matija (Priest) on Mar 04, 2004 at 16:09 UTC
    Straight from perldoc Net::FTP:
    $ftp->cwd("/pub") or die "Cannot change working directory ", $ftp->message;
Re: Problem using Net::FTP
by jarich (Curate) on Mar 04, 2004 at 18:59 UTC
    Okay, the problem is that you're ftping as many files as the info file provides you with. If this usually contains 2 files then that's great, but you probably want to allow it to later contain 3 or 4 or more, for flexibility's sake.

    If you're happy with this idea, then you'll probably realise that specifying the directory that you want the file to be ftped into inside the info file, with the renaming information is a good idea.

    Before I get to that I just want to bring up one problem I immediately had with your script:

    open(FILE, "<info>"); while (<FILE> ) {

    Firstly, I don't think you actually mean to have that > there. Secondly you're not checking that your open succeeded. What if you're not allowed to read the file? Permission denied? You should definately check this.

    So anyway, we can fix your code like this:

    # open the file safely or complain it wouldn't open open(FILE, "<", "info") or die "Failed to open info file: $!"; while (<FILE> ) { s/\W*$//; # remove trailing whitespace next if (!$_); # skip empty lines # check that we get our match. If not, # complain and move on unless(/^(.+?) \s+ (.+?) \s+ (.+?)$/x) { print STDERR "$_ is not a valid line"; next; } my ($old, $new, $ftpdir) = ($1, $2, $3); rename $old, $new; # ftp transfer my $server = "X.X.X.X"; my $ftp = Net::FTP->new ($server, Timeout => 9000, Debug => 3) +; $ftp or die "$server: cannot connect: $@"; # If you don't use ~/.netrc $ftp->login ('anonymous', 'mail@adress') or die "$_: cannot logon: " . $ftp->message; # change remote directory for the first file $ftp->cwd($ftpdir); # use directory from file # Send file to ftp server $ftp->put($new) or die "$server: cannot put $new: " . $ftp->message; # Sleep for 20 minutes before processing next file. sleep (20 * 60) }

    I really don't like your regular expression to pull the filenames out of the line. It's open to getting all sorts of things wrong. I'd suggest you instead change it to something like:

    #Expect 2 filenames and a directory path /^([\w._-] \s+ ([\w._-]) \s+ ([\w._\/-]$)/;
    This prevents people from entering the following lines and getting interesting results:
    /home/jarich/passwd /etc/passwd abc a b c
    In the first case it's pretty easy to spot what $1, $2 and $3 are set to and I hope you understand why that might be a bad thing. In the second case we get this:
    $1 = "a "; $2 = "b "; $3 = "c"
    Why all those spaces when you have \s+? Because .* is greedy from the left, not from the right.

    I'd suggest you work out what characters you want to allow in your filenames and only accept those. I've given you a good start. [\w._-] only accepts letters, numbers, dots, underscores and dashs. If you need anything else then add that in... with caution. Oh, and make sure you add them before the dash, not after. This will probably help you in the future too.

    One final thing. Notice how using identation makes the script easier to read? You might want to make a special effort on that next time you post here.

    all the best, and I hope this helps

    jarich

      thanks jarich
      for the great and very competent support,
      but I wrote my problems not so clearly.

      the info file looks :
      ----------------------
      AB00001 N120001
      BB00002 N200023
      ----------------------
      with info file I should get many times a day
      also 2 files: AB00001 and BB00002
      all files are TEXT files.
      left above is the name of the first file and at the bottom left hand corner the name of the second file.

      script should check if the files are complete and names on info file matches to the names of this 2 files.
      only if complete, rename first file to N120001 transfer,
      wait for 20 minutes, rename the second to N200023 and transfer to the different directory then the first one.
      the name of the info file never changed, but names of these 2 files and names on the info file change all the time.
      on info file I don't get any paths to change directory on the ftp server.
      these paths are fixed:
      already renamed first file N120001 should be transfered to:
      $ftp->cwd("FTP/A1");
      and second file N200023 to:
      $ftp->cwd("FTP/B2");
      this is, I think my biggest problem at the moment.

      when the transfer completed should create a new subdirectory with date and time, something like: 200402241200
      and put (backup) all files there, otherwise files will be overwritten each time.

      this script will be scheduled every 5 minutes from cron job and waits for the files.

      there are very important things:
      the second file cannot be transfered without the first one
      the second file must be transfered after 20 minutes after the first transfer.
      these files cannot be transfered twice and should be there.

      and I would like use your script, that you already posted.
      if you have time to help by this script, I 'll be very happy
      I know, it's a lot of changes, but I want to explain,
      what should do this script on the end.

      kind regards
      cc
        the info file looks :
        ----------------------
        AB00001 N120001
        BB00002 N200023
        ----------------------
        However, because the code looks like:
        while (<FILE> ) {
        you will process as many files as the info file has lines. So, if the info file were to be replaced with something like this:
        AB00001 N120001 BB00002 N200023 CB00003 N300011 DB00004 N400022
        then your code will attempt to ftp and rename each of those 4 files.

        If you want to limit the number of files processed to always be two and only two then you don't want to use a while loop. Perhaps a for loop would be better:

        # replace the while(<FILE>) { with the following two lines for(my $i = 1; $i <= 2; $i++) { $_ = <FILE>;

        script should check if the files are complete and names on info file matches to the names of this 2 files.
        I have no idea what this means.

        first file N120001 should be transfered to: $ftp->cwd("FTP/A1"); and second file N200023 to: $ftp->cwd("FTP/B2");
        If you can't change what gets put into the info file then my suggestion the other day won't work as well. If you can change it then that would probably make better sense. This way the directory names to ftp things to aren't hard coded in your script and therefore may be easier to change in future.

        Assuming you can't make the changes to the info script then you might want to change your script to look more like:

        # ftp directories my @ftp_locations = ("FTP/A1", "FTP/B2"); # open the file safely or complain it wouldn't open open(FILE, "<", "info") or die "Failed to open info file: $!"; while (<FILE> ) { s/\W*$//; # remove trailing whitespace next if (!$_); # skip empty lines # check that we get our match. If not, # complain and move on. Want to see two # filenames. unless(/^([\w.-]) \s+ ([\w.-])$/x) { print STDERR "$_ is not a valid line"; next; } my ($old, $new) = ($1, $2); rename $old, $new; # Now that we have our filenames, grab an # ftp directory from the list unless(@ftp_locations) { die "Not enough specified ftp_locations for ". "given number of files!"; } my $destination = shift @ftp_locations; # ftp transfer my $server = "X.X.X.X"; my $ftp = Net::FTP->new ($server, Timeout => 9000, Debug => 3) +; $ftp or die "$server: cannot connect: $@"; # If you don't use ~/.netrc $ftp->login ('anonymous', 'mail@address') or die "$_: cannot logon: " . $ftp->message; # change remote directory for the first file $ftp->cwd($destination); # Send file to ftp server $ftp->put($new) or die "$server: cannot put $new: " . $ftp->message; # Sleep for 20 minutes before processing next file. sleep (20 * 60) }
        Note that this still allows you to deal with more than 2 files in the info file, but only if you add additional ftp locations into the array up the top.

        when the transfer completed should create a new subdirectory with date and time, something like: 200402241200 and put (backup) all files there, otherwise files will be overwritten each time.
        How about you give this bit a go and get back to us with how you do at it?

        and I would like use your script, that you already posted.
        Ah, but of course. Certainly, go ahead and use the code I've provided you with. Good luck with the rest.

        Hope this helps,

        jarich

Re: Problem using Net::FTP
by neniro (Priest) on Mar 04, 2004 at 17:17 UTC
    I've seen this post, in the german perl community board, before?!
    #Please use more significant titles!
    --okay, jdporter changed the title.