Håkon Hægland
Håkon Hægland

Reputation: 40718

Determine absolute path of module without using require

In some cases you need to determine the absolute path name of a Perl module, but you do not need to load the Perl module:

use strict;
use warnings;

my $mod_name = 'My::Module';
my $abs_path = mod_name_to_abs_path( $mod_name );

sub mod_name_to_abs_path {
    my ( $mod_name ) = @_;

    my $rel_fn = $mod_name =~ s{::}{/}gr;
    $rel_fn .= '.pm';
    require $rel_fn;

    return $INC{$rel_fn};
}

The above code loads the module (with require).

How can I determine the absolute path name of a module without using require?

Upvotes: 3

Views: 103

Answers (2)

Borodin
Borodin

Reputation: 126722

The Module::Util module provides the find_installed function which does what I think you need.

There is also the object-oriented Module::Info and Module::Data modules which will do something superficially similar

This program shows the use of all three

use strict;
use warnings 'all';
use feature 'say';

use Module::Util 'find_installed';
use Module::Info ();
use Module::Data ();

say find_installed('Module::Util');

say Module::Info->new_from_module('Module::Info')->file;

say Module::Data->new('Module::Data')->path;

output

C:\Strawberry\perl\site\lib\Module\Util.pm
C:\Strawberry\perl\site\lib\Module\Info.pm
C:\Strawberry\perl\site\lib\Module\Data.pm

Upvotes: 6

Håkon Hægland
Håkon Hægland

Reputation: 40718

I am posting this solution to my own question since I could not find a CPAN module that did this.

use strict;
use warnings;
use File::Spec;

my $mod_name = 'My::Module';
my $abs_path = mod_name_to_abs_path( $mod_name );

sub mod_name_to_abs_path {
    my ( $mod_name ) = @_;

    my $rel_fn = $mod_name =~ s{::}{/}gr;
    $rel_fn .= '.pm';
    my $abs_path;
    for my $dir (@INC) {
        if ( !ref( $dir ) ) {
            my $temp = File::Spec->catfile( $dir, $rel_fn );
            if ( -e $temp  ) {
                if ( ! ( -d _ || -b _ ) ) {
                    $abs_path = $temp;
                    last;
                }
            }
        }
    }
    return $abs_path;
}

Upvotes: 7

Related Questions