[oak perl] listing modules
Steve Fink
sfink at reactrix.com
Tue Sep 14 16:27:56 CDT 2004
Belden Lyman wrote:
> On Tue, 2004-09-14 at 12:54, Steve Fink wrote:
>
>>>On Tue, 2004-09-14 at 09:49, David Fetter wrote:
>>>
>>>
>>>>On Tue, Sep 14, 2004 at 08:39:24AM -0700, Belden Lyman wrote:
>>>>
>>>>>That only tells you the modules installed by whomever has write
>>>>>permission on perllocal.pod.
>>>>
>>>>True. Short of find / or locate, is there some other way to find
>>>>the rest?
>>
>>Well, they all have to be findable through @INC, so would this get you
>>something close enough?
>>
>> perl -le 'print foreach map { glob("$_/*.pm") } @INC'
>
>
> No, that's not true. lib.pm, -I switch to perl, and installation of
> modules into home directories can all yield modules findable by a
> particular instance of the perl interpreter, yet not located anywhere
> within @INC.
Those are not installed modules. I certainly wouldn't want it to find
modules that I had downloaded but never installed, so I also wouldn't
want it to find modules in places like that.
> Even if that were the case, your one-liner wouldn't work for modules
> such as IO::Socket::INET, because $_ would never be IO/Socket. A
> different approach would be:
>
> perl -MFile::Find -le'find(sub{/\.pm$/ and print
> $File::Find::name}, at INC)'
Good point! Yes, that is much better. It still isn't guaranteed to be
complete (it doesn't search the rarely-used .pmc files, nor does it
handle CODE refs stuck into @INC by some installed module that then
allow you to find other modules), and it will probably contain more than
you want (my @INC contains . by default, which I've never liked, and
therefore finds all kinds of uninstalled modules depending on where I
run it from), but it seems about right.
The one problem I have with that script is that it is only giving me the
basename of each file, which makes it hard to figure out what A.pm is
(it's Net::FTP::A, or perhaps Net::DNS::RR::A). I never use File::Find,
but from the docs I don't understand why not. At any rate, you can get
the full path with
perl -MFile::Find -le 'find({wanted=>sub{/\.pm$/ and print
$File::Find::name}, no_chdir=>1}, at INC)'
but I'm sure there must be a better solution (especially one that gets
rid of the @INC entry from the beginning of the path!). Oh, and get rid
of the stupid current directory:
perl -MFile::Find -le 'find({wanted=>sub{/\.pm$/ and print
"$File::Find::name $File::Find::dir"}, no_chdir=>1},grep{$_ ne "."}@INC)'
Are we recreating the script from perlmonks? I already deleted that
message, so I can't go back and check.
With my bias against File::Find (and for glob()), I'd probably do the
whole thing like
perl -le '@d=map {[$_,$_]} sort {length($b)<=>length($a)} grep
{!/^\./} @INC; while(@d) {($_,$d)=@{shift @d}; next if $e{$_}++; print
substr($_, 1+length($d)) if /\.pm$/; push @d, map {[$_,$d]} glob("$_/*")
if -d $_}'
but that took me a while to come up with, and has gone way over the
one-liner threshold. :-) I just prefer doing the search explicitly,
because I always find myself wanting more control and not wanting to try
to track down some oddly-named configuration setting to do half of what
I want.
Back to work. No email checking for a while.
More information about the Oakland
mailing list