Problematic Perl code

P

PerlNovice

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

Eric Schwartz

PerlNovice said:
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
 
I

Ian Wilson

PerlNovice said:
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?
 
P

PerlNovice

-------------------------------------------------
#!/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?
 
P

Paul Lalli

PerlNovice said:
-------------------------------------------------
#!/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
 
P

Paul Lalli

PerlNovice said:
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
 
J

Joe Smith

Eric said:

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
 
J

Joe Smith

PerlNovice said:
... 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
 
E

Eric Schwartz

Joe Smith said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top