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

Dear monks,

I have YAEP - yet another efficiency problem (but you could also think of it as "Yet another elegance problem"): I'm doing a glob expansion of a list. let's say you have a list @params and this contains some filename globs. You'd like to expand this list to be explicit. i.e.

(*.txt *.aux) -> (file1.txt file2.txt file1.aux file2.aux)
So ok. What I'm doing right now is:
sub globlist { my @back; foreach my $elem (@_) { push @back, (glob $elem); } return @back; }
and then just @param = &globlist(@param); Waaah. Bad solution. I know it - I feel it. Much copying way too much overhead, too much code. I'd like to walk through the list and modify it without copying the expanded data to a new one. But when I try splice to do that, I get lost with the index.

Does anyone of you know the right path to listglobing?

Bye
 PetaMem

Replies are listed 'Best First'.
(MeowChow) Re: Listglob
by MeowChow (Vicar) on Apr 17, 2002 at 10:52 UTC
    Creating a new return list is both more efficient and more elegant than any hack and splice solution. You're already on the right path ;) And as strat notes, glob is already designed for this. Why even write a sub?
    my @files = <@params>;
       MeowChow                                   
                   s aamecha.s a..a\u$&owag.print
Re: Listglob
by strat (Canon) on Apr 17, 2002 at 10:21 UTC
    I'm not sure if I understand you correctly; but maybe references might help you and the fact that glob also allows more parameters ...
    sub globlist { my @back = glob("@_"); # list with spaces between: take care: # $" has to contain a space to do so # or write better: my @back = glob (join(" ", @_)); return \@back; } my $paramArrayRef = &globlist(@param);

    Another idea: As glob's are not really fast, could it improve the performance if you work with opendir and readdir and do the filtering that way?

    Best regards,
    perl -le "s==*F=e=>y~\*martinF~stronat~=>s~[^\w]~~g=>chop,print"

Re: Listglob
by ariels (Curate) on Apr 17, 2002 at 13:18 UTC
    AWTDI: map knows how to deal with lists...
    map { glob } @param
Re: Listglob
by tachyon (Chancellor) on Apr 17, 2002 at 12:46 UTC

    You can roll your own thusly:

    my @param = qw( *.txt *.p? ); print "$_\n" for find( \@param, 'c:/' ); sub find { my ($finds, $dir) = @_; $dir ||= './'; # defult to CWD if no dir supplied opendir D, $dir or die "Can't read $dir $!"; my @file_list = grep { ! -d $dir.$_ and ! -l $dir.$_ }readdir D; closedir D; my @terms; # modify * to .* and ? to . and quotemeta rest so regex friendly for my $term (@$finds) { $term = quotemeta $term; $term =~ s/\\\*/.*/g; $term =~ s/\\\?/./g; push @terms, $term; } # build regex my $re = '(?:' . (join "|", @terms) . ')'; $re = qr/$re/; return grep { /^$re\z/s } @file_list; }

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      Doesn't work if the pattern is foo*/*bar, since you are doing only one readdir. As others have said in this thread already, why reinvent the glob built-in?

      -- Randal L. Schwartz, Perl hacker

        Don't shout, you're hurting my eyes. As for why. Why not? Do you always drive just because it's faster? Would you not climb Everest because other have before you? Do you refuse to breath because others have been there, done that? Give the don't reinvent the wheel bit a break.

        cheers

        tachyon

Re: Listglob
by Zaxo (Archbishop) on Apr 17, 2002 at 19:12 UTC

    How about:

    my @globlist = glob '*.{txt,aux}';
    That is a shell glob expression, but we're assured it's portable.

    After Compline,
    Zaxo

      my @globlist = glob '*.{txt,aux}';

      That is a shell glob expression, but we're assured it's portable.

      Actually, that's a csh or ksh glob expression, not a shell glob expression. And since Perl would actually run on machines that didn't have csh (gasp!), it's not completely portable in the same sense as Perl.

      However, the difference would probably be nil for most modern Perl users.

      -- Randal L. Schwartz, Perl hacker

        However, there's little reason to gratitutiously break portablity when (glob('*.txt'), glob('*.aux')) would work.


        We are using here a powerful strategy of synthesis: wishful thinking. -- The Wizard Book

        Doesn't the glob funtion use File::Glob now? If so I think it would be 100% portable. (I'm sure you'll let me know if I'm wrong ;)