Search code examples
perlftpwildcardquotesls

perl quoting in ftp->ls with wildcard


contents of remote directory mydir :

blah.myname.1.txt
blah.myname.somethingelse.txt
blah.myname.randomcharacters.txt
blah.notmyname.1.txt
blah.notmyname.2.txt
...

in perl, I want to download all of this stuff with myname

I am failing really hard with the appropriate quoting. please help.

failed code

my @files;
@files = $ftp->ls( '*.myname.*.txt' );  # finds nothing
@files = $ftp->ls( '.*.myname.*.txt' );  # finds nothing

etc..

How do I put the wildcards so that they are interpreted by the ls, but not by perl? What is going wrong here?


Solution

  • I will assume that you are using the Net::FTP package. Then this part of the docs is interesting:

    ls ( [ DIR ] )

    Get a directory listing of DIR, or the current directory.

    In an array context, returns a list of lines returned from the server. In a scalar context, returns a reference to a list.

    This means that if you call this method with no arguments, you get a list of all files from the current directory, else from the directory specified.

    There is no word about any patterns, which is not suprising: FTP is just a protocol to transfer files, and this module only a wrapper around that protocoll.

    You can do the filtering easily with grep:

    my @interesting = grep /pattern/, $ftp->ls();
    

    To select all files that contain the character sequence myname, use grep /myname/, LIST.
    To select all files that contain the character sequence .myname., use grep /\.myname\./, LIST.
    To select all files that end with the character sequence .txt, use grep /\.txt$/, LIST.

    The LIST is either the $ftp->ls or another grep, so you can easily chain multiple filtering steps.

    Of course, Perl Regexes are more powerful than that, and we could do all the filtering in a single /\.myname\.[^.]+\.txt$/ or something, depending on your exact requirements. If you are desperate for a globbing syntax, there are tools available to convert glob patterns to regex objects, like Text::Glob, or even to do direct glob matching:

    use Text::Glob qw(match_glob);
    
    my @interesting = match_glob ".*.myname.*.txt", $ftp->ls;
    

    However, that is inelegant, to say the least, as regexes are far more powerful and absolutely worth learning.