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

Hi Monks,

I am trying to write a very simple program that will be

called from other scripts.

I want to ftp from a machine into another machine,

do a find,ftp all the files, not the directories

(.: or ..:) and close my connection.

So far, I have it where I can do the 'find', but I think I am

doing the 'find' in the local machine, also, I can't figure out how

to place the results of the 'find' into an array so I can later

do a 'foreach' loop on the array.

Any pearls of wisdom?

I also know that there are other programs like 'mirror', but

I am trying to keep mine very simple. just the guts.

Really appreciate the help

Here is my program for your amusement

#!/usr/local/bin/perl use Net::FTP; use File::Find; @ARGV = "." unless @ARGV; sub showfiles { print "$File::Find::name/\n" if !-d; } my $dir = '/my/remote/directory/path'; my $host = '123.45.67.890'; my $login = 'userlogin'; my $passwd = 'userpassword'; my $ftp = Net::FTP->new($host); my $RC = $ftp->login("$userlogin","$userpassword"); if (not $RC) { print "\n\nFTP Login to Remote Host: '$host' failed!\n\n"; print "No files updated from Remote host: '$host'!\n\n"; exit; } # Go to the specified directory print STDERR "Changing directory to <$dir>\n" if ($DEBUG); if ($ftp->cwd($dir) == 0) { warn "$program: can't change directory to <$dir>\n"; return(1); } find(\&showfiles, @ARGV); $ftp->quit;

Replies are listed 'Best First'.
Re: ftp'ing 'Find' results from an array
by simeon2000 (Monk) on Aug 13, 2002 at 17:58 UTC
    IIRC, the File::Find module doesn't work in conjunction with the FTP module. In other words, you're only getting a File::Find on the subdirectories of the client folder specified.

    FTP, in fact, probably would never be able to accomplish this. I'm not even sure how you'd do this, unless you sent and recieved perl code/data over TCP/IP client/server, or do an NFS mount or something like that.

    --
    perl -e "print qq/just another perl hacker who doesn't grok japh\n/"
    simeon2000|http://holdren.net/

Re: ftp'ing 'Find' results from an array
by Tomte (Priest) on Aug 13, 2002 at 18:18 UTC
    I want to ftp from a machine into another machine, do a find,ftp all the files, not the directories

    do you mean getting or putting them by "ftp" them?

    and further:

    $> perldoc Net::FTP /find
    returns pattern not found (press RETURN) there is no ftp-connection-oriented part in your find(...) statement. perldoc File::Find contains no ftp-related information.

    I'm just curious, really no pun intended, after reading the docs, why did you think this should work?

    If the file-count on the ftp-server side isn't to large, your recursive ls approach should work ok, because you can perform the find in your perl-script, it is kind of brute force, though.

    maybe if you comment a bit on why you want to do that, the monastery may come up with a feasible solution


    regards,
    tomte
      Thanks for your notes. I have also tried
      @data=$ftp->ls("-R"); foreach $line (@data) { $ftp->get($line); print $line."\n"; }
      But it doesn't work because it stops at the . or .. directories. The 'get' line chokes there. My 'Find' question obviously won't work as it only returns me the local files. I am just out of tricks on this one. In short, what I am trying to do, is: FTP there cd to a dir. get all the files there and below. close connection. seems simple.

        You could try somthing like this (untested!)

        @data=$ftp->ls("-R"); foreach $line (@data) { if !($line =~ m/^\.{1,2}/){ print "fetching " . $line . "\n"; $ftp->get($line) ; } }

        It sounds though as if wget or rsync could be useful in your case ( I don't know if there are modules out there providing the same functionality). you can call both tools via system, if the ftp-get part is just a fraction of the big picture of your project.

        Update: changed punctuation to clarify the meaning


        regards,
        tomte
Re: ftp'ing 'Find' results from an array
by Ebany (Sexton) on Aug 13, 2002 at 20:33 UTC
    Ok, I tackled something similar, but not exactly the same. Essentially, in my case, I wanted to build a link tree by ftping into a bunch of different accounts, and then going through each directory, and finding all the physical files, and then printing those out. I belive my situation maybe applicable though, as it would only take a small bit of hacking to put in a ftp->get()

    Note: This is code extract! Concept is the same though. Assume that warnings et all are included, and certain parts are excluded for brevity. Also, this was made for ftping into a VMS system. The program does work.

    my $ftpSession; if (login($current, getPass($current))) { @dirs = retrDirs(); @goodFiles = retrFiles(); foreach (@goodFiles) { {Insert code here} } if (@dirs) { foreach (@dirs) { _recparseTree ($_,""); } } } #This begins a new ftp session with a passed username and password sub login { my ($user, $pass) = @_; $ftpSession = Net::FTP->new($server, Debug => 0) or die printError +Entry ("", "Error logging into server."); $ftpSession->login($user,$pass) or return 0; $ftpSession->cwd("{base dir}"); return 1; } #This simply gets the current directory. sub getStruct { return $ftpSession->ls(); } #This reads the current directory, and picks out all .html, .htm, .htm +lx, and .pdf files, and returns an array sub retrFiles { my @tempfiles = getStruct(); my @results; foreach (@tempfiles) { if ($_ =~ m{\.HTM} || $_ =~ m{\.PDF} ) { push(@results,$_); } } return @results; } #This reads the current directory, and picks out all subdirectories, r +eturning an array of results sub retrDirs { my @tempdirs = getStruct(); my @results; foreach (@tempdirs) { if ($_ =~ m{\.DIR} ) { push(@results,substr($_,0, index($_,"."))); } } return @results; } sub _recparseTree { #get directory name my ($dir, $dirname) = @_; $dirname.= "\/".$dir; #Change directory to target $ftpSession->cwd("[.$dir]"); #Get the structure my @tempList = retrFiles(); my @tempDirs = retrDirs(); #If there are files in the directory. if (@tempList) { {Insert code here} foreach (@tempList){ {Insert code here} } } if (@tempDirs) { foreach (@tempDirs) { _recparseTree($_, $dirname) +; } } $ftpSession->cwd(".."); }


    This is not meant to be a running program, but hopefully an example you can use. Essentially, in order to mimic File::Find, I go through utilizing dual arrays to keep track of all files and directories, and navigate with those.

    Edit: Deleted some extraneous lines of code