Problematic Perl code

Discussion in 'Perl Misc' started by PerlNovice, Jan 2, 2007.

  1. PerlNovice

    PerlNovice Guest

    I have the following Perl code:

    -------------------------------------------------
    #!/usr/bin/perl
    use Net::FTP;
    $ftp = Net::FTP->new("some.host.name", Debug => 1)
    or die "Cannot connect to some.host.name: $@";
    $ftp->login("anonymous",'-anonymous@')
    or die "Cannot login ", $ftp->message;
    $ftp->cwd("/myfolder")
    or die "Cannot change working directory ", $ftp->message;
    $ftp->binary;
    for( <*.zip> ){
    $ftp->get($_,"tmp.$$") or die $!;
    $ftp->rename("tmp.$$",$_) or die $!;
    $ftp->size($_) == -s $_ or die "$_ sizes don't match";
    }
    $ftp->quit;
    -----------------------------------------------

    I need to do the following:

    1)I need to copy .zip files from Windows to my Unix folder and name the
    ..zip files as something else, let's say, .txt. I then need
    to rename it back to .zip only when the entire file has been copied.
    This is because I'll be unzipping the files later.
    There could be multiple .zip files in the Windows folder.

    2)Once the file(s) are copied completely, a size comparison needs to be
    made between the Windows and Unix sides.

    3)If the sizes are the same, then I need to rename the .txt file back
    to the .zip file.

    I would appreciate any help from anyone.
    PerlNovice, Jan 2, 2007
    #1
    1. Advertising

  2. "PerlNovice" <> writes:
    > 1)I need to copy .zip files from Windows to my Unix folder and name the
    > .zip files as something else, let's say, .txt. I then need
    > to rename it back to .zip only when the entire file has been copied.


    Why?

    In any event, did you read the docs for Net::FTP? Because in the
    documentation for the get() method, which you use in your code, it
    says explicitly:

    get ( REMOTE_FILE [, LOCAL_FILE [, WHERE]] )
    Get "REMOTE_FILE" from the server and store locally. "LOCAL_FILE"
    may be a filename or a filehandle. If not specified, the file will
    be stored in the current directory with the same leafname as the
    remote file.

    It's not considered polite in this newsgroup to ask people to read
    documentation for you if you can read it yourself.

    > This is because I'll be unzipping the files later.


    You can still do that if you don't rename them first, you know.

    > There could be multiple .zip files in the Windows folder.


    That's irrelevant to whether or not you rename them when you get them.

    > 2)Once the file(s) are copied completely, a size comparison needs to be
    > made between the Windows and Unix sides.


    Again, in the docs for Net::FTP it says mentions the size() method. I
    leave it as an excercise for the reader to figure out how to use it,
    and how to use the corresponding -s function on the local side (hint:
    'perldoc -f -X')

    > 3)If the sizes are the same, then I need to rename the .txt file back
    > to the .zip file.


    perldoc -f rename

    > I would appreciate any help from anyone.


    In return, I, and many others, would appreciate it if you would take a
    bit of time before posting to read the relevant documentation you
    already have on your hard drive before asking a bunch of people to do
    it for you.

    -=Eric
    Eric Schwartz, Jan 2, 2007
    #2
    1. Advertising

  3. PerlNovice

    Ian Wilson Guest

    PerlNovice wrote:
    > I have the following Perl code:


    But where? I'll assume its on your "Unix" computer and that
    "some.host.name" is your Windows computer.

    >
    > -------------------------------------------------
    > #!/usr/bin/perl
    > use Net::FTP;
    > $ftp = Net::FTP->new("some.host.name", Debug => 1)
    > or die "Cannot connect to some.host.name: $@";
    > $ftp->login("anonymous",'-anonymous@')
    > or die "Cannot login ", $ftp->message;
    > $ftp->cwd("/myfolder")
    > or die "Cannot change working directory ", $ftp->message;
    > $ftp->binary;
    > for( <*.zip> ){
    > $ftp->get($_,"tmp.$$") or die $!;
    > $ftp->rename("tmp.$$",$_) or die $!;
    > $ftp->size($_) == -s $_ or die "$_ sizes don't match";
    > }
    > $ftp->quit;
    > -----------------------------------------------


    I haven't tried the above but, from a superficial glance, it looks like
    it should work.

    >
    > I need to do the following:
    >
    > 1)I need to copy .zip files from Windows to my Unix folder and name the
    > .zip files as something else, let's say, .txt.


    The code does that already!

    > I then need
    > to rename it back to .zip only when the entire file has been copied.


    The code does that already!

    > This is because I'll be unzipping the files later.
    > There could be multiple .zip files in the Windows folder.
    >
    > 2)Once the file(s) are copied completely, a size comparison needs to be
    > made between the Windows and Unix sides.


    The code does that already!

    >
    > 3)If the sizes are the same, then I need to rename the .txt file back
    > to the .zip file.


    swap the order of the two lines that start $ftp->rename and $ftp->size

    > I would appreciate any help from anyone.
    >


    I must be missing something. You seem to be saying ...
    Here is a working solution.
    Here is the problem it solves.
    Help!

    What exactly does the code do that you don't want it to do?
    Ian Wilson, Jan 3, 2007
    #3
  4. PerlNovice

    PerlNovice Guest

    -------------------------------------------------
    #!/usr/bin/perl
    use Net::FTP;
    $ftp = Net::FTP->new("some.host.name", Debug => 1)
    or die "Cannot connect to some.host.name: $@";
    $ftp->login("anonymous",'-anonymous@')
    or die "Cannot login ", $ftp->message;
    $ftp->cwd("/myfolder")
    or die "Cannot change working directory ", $ftp->message;
    $ftp->binary;
    for( <*.zip> ){
    $ftp->get($_,"tmp.$$") or die $!;
    $ftp->rename("tmp.$$",$_) or die $!;
    $ftp->size($_) == -s $_ or die "$_ sizes don't match";
    }
    $ftp->quit;
    -----------------------------------------------

    Thank you for your responses. Ian, this code does NOT work. It runs,
    does not produce any error, but doesn't bring the file from Windows to
    UNIX. I don't understand the For loop. For every .zip file, it puts it
    in the variable $_. What is:

    get($_,"tmp.$$")
    Does that mean that every .tmp file is put in $_? Why do we use tmp.$$?

    size($_) == -s $_ : What does this do?
    PerlNovice, Jan 3, 2007
    #4
  5. PerlNovice

    Paul Lalli Guest

    PerlNovice wrote:
    > -------------------------------------------------
    > #!/usr/bin/perl
    > use Net::FTP;
    > $ftp = Net::FTP->new("some.host.name", Debug => 1)
    > or die "Cannot connect to some.host.name: $@";
    > $ftp->login("anonymous",'-anonymous@')
    > or die "Cannot login ", $ftp->message;
    > $ftp->cwd("/myfolder")
    > or die "Cannot change working directory ", $ftp->message;
    > $ftp->binary;
    > for( <*.zip> ){
    > $ftp->get($_,"tmp.$$") or die $!;


    This code makes no sense of any kind. You are iterating through every
    ..zip file *on the local machine*, and attempting to retrieve a file of
    the same name *on the remote machine*, saving that file back to the
    local machine as the name "tmp.$$" ($$ is the process id of the current
    process).

    > $ftp->rename("tmp.$$",$_) or die $!;


    And this makes even less sense. Now you're trying to access a file
    named $tmp.$$ *on the remote machine*, and change it's name to the file
    you just tried to retrieve. $tmp.$$ never existed on the remote
    machine. Even if it did, you'd then be overwriting the file whose
    contents you just copied.

    > $ftp->size($_) == -s $_ or die "$_ sizes don't match";
    > }
    > $ftp->quit;
    > -----------------------------------------------
    >
    > Thank you for your responses. Ian, this code does NOT work. It runs,
    > does not produce any error, but doesn't bring the file from Windows to
    > UNIX. I don't understand the For loop. For every .zip file, it puts it
    > in the variable $_. What is:
    >
    > get($_,"tmp.$$")
    > Does that mean that every .tmp file is put in $_? Why do we use tmp.$$?
    >
    > size($_) == -s $_ : What does this do?


    Wait a minute. Your original post said "I have this code". That is
    generally meant to mean "I've written this code". Now it's pretty
    clear that you didn't write it. Well, frankly, good for you, because
    it's crap. But more importantly, why aren't you asking the person who
    did write it to fix it, rather than asking us to explain it to you?

    Throw that mess away, read the docs from Net::FTP, and start your own
    script. When you encounter problems with YOUR OWN code, let us know,
    and we can probably help you.

    Paul Lalli
    Paul Lalli, Jan 3, 2007
    #5
  6. PerlNovice

    Paul Lalli Guest

    PerlNovice wrote:
    > I have the following Perl code:
    >
    > -------------------------------------------------
    > #!/usr/bin/perl
    > use Net::FTP;
    > $ftp = Net::FTP->new("some.host.name", Debug => 1)
    > or die "Cannot connect to some.host.name: $@";
    > $ftp->login("anonymous",'-anonymous@')
    > or die "Cannot login ", $ftp->message;
    > $ftp->cwd("/myfolder")
    > or die "Cannot change working directory ", $ftp->message;
    > $ftp->binary;
    > for( <*.zip> ){
    > $ftp->get($_,"tmp.$$") or die $!;
    > $ftp->rename("tmp.$$",$_) or die $!;
    > $ftp->size($_) == -s $_ or die "$_ sizes don't match";
    > }
    > $ftp->quit;
    > -----------------------------------------------
    >
    > I need to do the following:
    >
    > 1)I need to copy .zip files from Windows to my Unix folder


    I have the distinct feeling that your central problem here is using
    get() instead of put(). On what machine is this program running - the
    Windows or the Unix? If it's running on Unix and you're trying to
    "get" the files from the Windows machine, you have several different
    logic problems - see my other response in this thread. If it's running
    on Windows, you should be using "put", not get. get() retrieves a file
    from the remote machine and stores it on the local machine. put()
    takes a file from the local machine and stores it on the remote
    machine.

    > and name the
    > .zip files as something else, let's say, .txt. I then need
    > to rename it back to .zip only when the entire file has been copied.


    Huh? Why do you think you need to name it as something else
    temporarily?

    > This is because I'll be unzipping the files later.


    That does not explain why you need to give it a temporary name...

    > There could be multiple .zip files in the Windows folder.


    .... and neither does that.

    > 2)Once the file(s) are copied completely, a size comparison needs to be
    > made between the Windows and Unix sides.
    >
    > 3)If the sizes are the same, then I need to rename the .txt file back
    > to the .zip file.


    And if they're not?

    Regardless, your program logic does not meet your description. You do
    the renaming *first* and then check the size.

    Paul Lalli
    Paul Lalli, Jan 3, 2007
    #6
  7. PerlNovice

    Joe Smith Guest

    Eric Schwartz wrote:
    > "PerlNovice" <> writes:
    >> 1)I need to copy .zip files from Windows to my Unix folder and name the
    >> .zip files as something else, let's say, .txt. I then need
    >> to rename it back to .zip only when the entire file has been copied.

    >
    > Why?


    So that the partially copied file won't be accessible.
    So that any existing file will can be accessed while the transfer is
    in progress.

    1) Copy the file to the destination directory using a temporary name.
    2) When the transfer is complete (which could take hours), delete the
    existing file (if any) and rename the temporary file to its proper name.

    It's the right thing to do on a multi-user or multitasking system.

    > It's not considered polite in this newsgroup to ask people to read
    > documentation for you if you can read it yourself.


    You've completely missed the point of what PerlNovice was asking.
    Reading the documentation on get() is not the answer in this case.
    -Joe
    Joe Smith, Jan 5, 2007
    #7
  8. PerlNovice

    Joe Smith Guest

    PerlNovice wrote:

    > ... copy .zip files from Windows to my Unix folder and name the
    > .zip files as something else, let's say, .txt. I then need
    > to rename it back to .zip only when the entire file has been copied.


    Using ".txt" is a bad idea. It is better to use ".part" or ".partial"
    to indicate that the file being received is not yet complete.

    > $ftp->cwd("/myfolder")
    > or die "Cannot change working directory ", $ftp->message;


    Do you really want use a name with a leading slash? Typical values for cwd()
    are "myfolder" or "directory/subdirectory" for folders relative to your
    login directory, or an absolute pathname like "/home/myname/mydir";

    > for( <*.zip> ){


    You've got a conceptual error there. That glob operator returns a list
    of files that already exist on your local machine. To get a list of
    available files on the FTP server, you need to ask the server and then
    parse the results.

    my @directory_listing = $ftp->dir() or die "Error ftp->dir() - ",$ftp->message;
    print "Files on server:\n", join "\n",@directory_listing,'' if $verbose;

    for my $line (@directory_listing) {
    # WARNING: Not all FTP servers use the Unix format for dir().
    my($perms,$links,$uid,$gid,$size,$mon,$day,$time,$file) = split ' ',$line,9;
    next unless $file =~ /\.zip$/i;

    > $ftp->get($_,"tmp.$$") or die $!;
    > $ftp->rename("tmp.$$",$_) or die $!;


    That's wrong. You need rename(), not $ftp->rename().

    my $temp_name = "$file.$$.partial";
    if ($ftp->get($file,$temp_name)) {
    -f $file and (unlink $file or warn "Could not remove old $file: $!\n");
    rename($temp_name,$name) or warn "Could not set name to $file: !$\n";
    } else {
    warn "get($file) failed: ", $ftp->message;
    }

    > $ftp->size($_) == -s $_ or die "$_ sizes don't match";


    my $received = -s $file;
    $received == $size or warn "Size mismatch for $file: $received != $size\n";

    > }
    >
    > I would appreciate any help from anyone.


    You can look at http://www.inwap.com/tivo/from-tivo as an example.
    -Joe
    Joe Smith, Jan 5, 2007
    #8
  9. Joe Smith <> writes:
    > Eric Schwartz wrote:
    > > It's not considered polite in this newsgroup to ask people to read
    > > documentation for you if you can read it yourself.

    >
    > You've completely missed the point of what PerlNovice was asking.
    > Reading the documentation on get() is not the answer in this case.


    How's that? For whatever reason (your explanation is most probable,
    and I'm kicking myself for not thinking of it), he wanted to copy a
    file from a remote server to the local machine and rename it at the
    same time. That's what Net::FTP::get() is for. I notice your reply
    to him uses exactly the feature of that method I suggested the OP use,
    so why, pray tell, was it not relevant?

    -=Eric
    Eric Schwartz, Jan 5, 2007
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Lim Siew Cheng

    Re: Problematic Postbacks

    Lim Siew Cheng, Aug 12, 2003, in forum: ASP .Net
    Replies:
    3
    Views:
    371
    IbrahimMalluf
    Aug 12, 2003
  2. Duray AKAR

    Problematic Postbacks

    Duray AKAR, Aug 12, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    325
    Duray AKAR
    Aug 12, 2003
  3. Eric Lilja
    Replies:
    3
    Views:
    621
    kwikius
    Jul 1, 2006
  4. Gregor H.

    Problematic code in K&R

    Gregor H., Apr 19, 2007, in forum: C Programming
    Replies:
    1
    Views:
    291
    Gregor H.
    Apr 19, 2007
  5. Replies:
    4
    Views:
    125
Loading...

Share This Page