http://www.perlmonks.org?node_id=1066904

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

I have the following script, which is supposed to recurse through Dell's ftp site and download text files. It gets in, but doesn't download anything. Any thoughts on why?

Below is the code and my analysis/questions.

#!/usr/bin/perl use strict; use warnings; use Carp; use Data::Dumper; use Net::hostent; #use Net::Ping; use Net::FTP::Recursive; my %params = ( site => "ftp.dell.com", dir => "Browse_For_Drivers/Servers, Storage & Networking/Power +Edge", ); FTPConnect (\%params); sub FTPConnect { my $ref_params = shift @_; my $retval = ""; my $ftp = Net::FTP::Recursive->new($ref_params->{site}, Debug => 1 +, Timeout => 15); if ($ftp) { $retval = "OK: connected via FTP to " . $ref_params->{site} . + "\n\n" ; $ftp->login("anonymous",'me@here.there'); $ftp->binary; $ftp->cwd($ref_params->{dir}); #$ftp->rget( ParseSub => \&GetFiles($ftp), $ftp->rget( ParseSub => \&GetFiles, FlattenTree => 1, #MatchDirs => qr/PowerEdge (R810|R610|R720|R62 +0|M620|M1000E)/, #MatchFiles => qr/\.txt/, ); $ftp->quit; } else { $retval = "ERROR: FTP for host $ref_params->{site}\n\n" } return $retval; } sub GetFiles { #my $my_ftp = shift @_; #$my_ftp->get("*.txt"); return; }
With nothing in GetFiles (only a return statement), I get this when I run it:

Net::FTP::Recursive=GLOB(0xa4bee8)<<< 250 CWD command successful. Net::FTP::Recursive=GLOB(0xa4bee8)>>> PWD Net::FTP::Recursive=GLOB(0xa4bee8)<<< 257 "/Browse_For_Drivers/Servers +, Storage & Networking/PowerEdge" is current directory. Net::FTP::Recursive=GLOB(0xa4bee8)>>> PASV Net::FTP::Recursive=GLOB(0xa4bee8)<<< 227 Entering Passive Mode (143,1 +66,147,12,231,73) Net::FTP::Recursive=GLOB(0xa4bee8)>>> LIST Net::FTP::Recursive=GLOB(0xa4bee8)<<< 150 Opening BINARY mode data con +nection. Net::FTP::Recursive=GLOB(0xa4bee8)<<< 226 Transfer complete. drwxrwxrwx 1 owner group 0 Aug 29 2012 Dell KVM 10 +81AD drwxrwxrwx 1 owner group 0 Sep 25 2012 Dell KVM 10 +82DS ... Net::FTP::Recursive=GLOB(0xa4bee8)>>> PWD Net::FTP::Recursive=GLOB(0xa4bee8)<<< 257 "/Browse_For_Drivers/Servers +, Storage & Networking/PowerEdge" is current directory. Net::FTP::Recursive=GLOB(0xa4bee8)>>> QUIT Net::FTP::Recursive=GLOB(0xa4bee8)<<< 221 Thank you for using the Dell + FTP site, please come again.
When I add the code to get files, I get the same, except for:
Net::FTP::Recursive=GLOB(0x1054fa8)<<< 250 CWD command successful. Net::FTP::Recursive=GLOB(0x1054fa8)>>> PASV Net::FTP::Recursive=GLOB(0x1054fa8)<<< 227 Entering Passive Mode (143, +166,135,12,255,118) Net::FTP::Recursive=GLOB(0x1054fa8)>>> RETR *.txt Can't use an undefined value as a symbol reference at /usr/share/perl5 +/Net/FTP/dataconn.pm line 54.
While I could put in code to search for and only download text files, I would have thought that would be already be built into the Recursive module. I get the feeling even modifying the GetFiles subroutine may be overkill, as the cpan page seems to imply (to me, at least) it's not needed. From that page:

If you'd like to provide your own function for parsing the data retrieved from this command (in case the ftp server does not understand the "dir" command), all you need do is provide a function to one of the Recursive method calls.

However, I'm not parsing the data, and I'd think I shouldn't need to, if the correct filter parameter is set. I'm referring to the FlattenTree => 1. From the cpan page:

The FlattenTree optional argument will retrieve all of the files from the remote directory structure and place them in the current local directory. This option will resolve filename conflicts by retrieving files with the same name and renaming them in a "$filename.$i" fashion, where $i is the number of times it has retrieved a file with that name. ... MatchFiles - Only transfer plainish (not a directory or a symlink) files that match this pattern. ... MatchDirs - Only recurse into directories that match this pattern.

I thought it was something with my regexes, so I commented those out, but still the same thing.

What am I missing here? Why isn't the script downloading the text files? UPDATE: Thanks all for your help. Splitting the code out in separate calls for each directory and removing the MatchDirs specification works.

-- Burvil