#!/usr/bin/env perl
# pminst -- find modules whose names match this pattern
# tchrist@perl.com
BEGIN { $^W = 1 }
use Getopt::Std qw(getopts);
use File::Find;
getopts('ls') || die "bad usage";
if (@ARGV == 0) {
@ARGV = ('.');
}
die "usage: $0 [-l] [-s] pattern\n" unless @ARGV == 1;
$pattern = shift();
$pattern =~ s,::,/,g;
no lib '.';
use vars qw($opt_l $opt_s %seen);
for $startdir (@INC) {
next if (!-d $startdir);
find(\&wanted, $startdir);
}
sub wanted {
if (-d && /^[a-z]/) {
# this is so we don't go down site_perl etc too early
$File::Find::prune = 1;
return;
}
# Some expansions of @INC have subdirs of other @INC directories in them;
# to wit:
# /opt/perl/lib/site_perl/5.8.8
# /opt/perl/lib/site_perl
# This will result in output, when looking for module Foo:
# Foo
# 5.8.8:Foo
# We add full module paths for found modules to %seen so
# we can skip them the next time around.
return unless ( /\.pm$/ and not exists $seen{$File::Find::name} );
local $_ = $File::Find::name;
($tmpname = $_) =~ s{^\Q$startdir/}{};
return unless $tmpname =~ /$pattern/o;
if ($opt_l) {
s{^(\Q$startdir\E)/}{$1 } if $opt_s;
}
else {
s{^\Q$startdir/}{};
s/\.pm$//;
s{/}{::}g;
print "$startdir " if $opt_s;
}
$seen{$File::Find::name}=1;
print $_, "\n";
}
__END__
=head1 NAME
pminst - find modules whose names match this pattern
=head1 SYNOPSIS
pminst [B<-s>] [B<-l>] [I<pattern>]
=head1 DESCRIPTION
Without argumnets, show the names of all installed modules. Given a
pattern, show all module names that match it. The B<-l> flag will show
the full pathname. The B<-s> flag will separate the base directory from
@INC from the module portion itself.
=head1 EXAMPLES
$ pminst
(lists all installed modules)
$ pminst Carp
CGI::Carp
Carp
$ pminst ^IO::
IO::Socket::INET
IO::Socket::UNIX
IO::Select
IO::Socket
IO::Poll
IO::Handle
IO::Pipe
IO::Seekable
IO::Dir
IO::File
$ pminst '(?i)io'
IO::Socket::INET
IO::Socket::UNIX
IO::Select
IO::Socket
IO::Poll
IO::Handle
IO::Pipe
IO::Seekable
IO::Dir
IO::File
IO
Pod::Functions
The -s flag provides output with the directory separated
by a space:
$ pminst -s | sort +1
(lists all modules, sorted by name, but with where they
came from)
$ oldperl -S pminst -s IO
/usr/lib/perl5/i386-linux/5.00404 IO::File
/usr/lib/perl5/i386-linux/5.00404 IO::Handle
/usr/lib/perl5/i386-linux/5.00404 IO::Pipe
/usr/lib/perl5/i386-linux/5.00404 IO::Seekable
/usr/lib/perl5/i386-linux/5.00404 IO::Select
/usr/lib/perl5/i386-linux/5.00404 IO::Socket
/usr/lib/perl5/i386-linux/5.00404 IO
/usr/lib/perl5/site_perl LWP::IO
/usr/lib/perl5/site_perl LWP::TkIO
/usr/lib/perl5/site_perl Tk::HTML::IO
/usr/lib/perl5/site_perl Tk::IO
/usr/lib/perl5/site_perl IO::Stringy
/usr/lib/perl5/site_perl IO::Wrap
/usr/lib/perl5/site_perl IO::ScalarArray
/usr/lib/perl5/site_perl IO::Scalar
/usr/lib/perl5/site_perl IO::Lines
/usr/lib/perl5/site_perl IO::WrapTie
/usr/lib/perl5/site_perl IO::AtomicFile
The -l flag gives full paths:
$ filsperl -S pminst -l Thread
/usr/local/filsperl/lib/5.00554/i686-linux-thread/Thread/Queue.pm
/usr/local/filsperl/lib/5.00554/i686-linux-thread/Thread/Semaphore.pm
/usr/local/filsperl/lib/5.00554/i686-linux-thread/Thread/Signal.pm
/usr/local/filsperl/lib/5.00554/i686-linux-thread/Thread/Specific.pm
/usr/local/filsperl/lib/5.00554/i686-linux-thread/Thread.pm
=head1 AUTHORS and COPYRIGHTS
Copyright (C) 1999 Tom Christiansen.
Copyright (C) 2006-2008 Mark Leighton Fisher.
This is free software; you can redistribute it and/or modify it
under the terms of either:
(a) the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any
later version, or
(b) the Perl "Artistic License".
(This is the Perl 5 licensing scheme.)
Please note this is a change from the
original pmtools-1.00 (still available on CPAN),
as pmtools-1.00 were licensed only under the
Perl "Artistic License".