簡単に書くと以下のようなかんじ。
collect-modules.pl
#!/usr/bin/env perl
use strict;
use warnings;
use File::Find;
use File::Spec;
my %modules = ();
my %inc = map { $_ => $_ } map { File::Spec->canonpath($_) } grep { -d $_ && $_ ne '.' } @INC;
for my $path (keys %inc) {
find(+{
wanted => sub {
my $name = $File::Find::fullname;
if (-d $name) {
if (exists $inc{$name} && $inc{$name} ne $path) {
$File::Find::prune = 1;
}
return;
}
return unless $name =~ s/\.pm\z//;
$name = File::Spec->abs2rel($name, $path);
my $module = join('::', File::Spec->splitdir($name));
$modules{$module}++;
},
follow => 1,
follow_skip => 2,
}, $path);
}
print "$_\n" for sort keys %modules;
@INC
以下(カレントディレクトリは除外)をFile::Find::find
でフルパス探索し、
- 拡張子で
*.pm
なファイルのみ抽出 -
@INC
の別要素に含まれているディレクトリ以下は探索を打ち切る -
$Config{archname}
以下のものなど複数のpath起点で抽出されるのを防ぐため -
File::Spec->abs2rel
を使って抽出されたファイルの相対パスを取得 -
/
を::
に置換
することで得られる。
helm-perldocではこの方式でモジュール一覧を取得している。
参照
-
perldoc perlfaq3
"How do I find which modules are installed on my system?" Section
cpan -l
はFile::Find::find
を使って@INC
以下の*.pmファイルのパスを取得した後、若干強引にモジュール名に変換している。cpan -a
はCPAN Indexからモジュール一覧を取得して その中からインストール済みのものをリストアップする、という方式。
ExtUtils::Installed
を使うとインストール済みの"ディストリビューション名"の一覧を取るには便利。ただし各ディストリビューションに含まれるモジュール一覧までは取得できない。