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

How do I reference a location that is relative to a Perl module? For example, I have some code in location A that uses a module in location B. Location B is 'somewhere' in the search path. Relative to location B (let's call it location Bx) I have a config file, a template, or whatever. Given that this module (and the asscoiated files) may be moved to another location of the search path, how do I reference location Bx without hard coding something into the module about either location B or Bx? I use BSD and $0 does not return a path.

Replies are listed 'Best First'.
Re: Location reference - programming style
by Your Mother (Archbishop) on Aug 14, 2010 at 22:10 UTC

    $0 returns a relative path. Since it works in OS X, I'm inclined to think it works in BSD just fine. You might also try __FILE__. Then look into File::Path, File::Spec->rel2abs, Cwd, FindBin, and Path::Class.

    This has come up here a bit so don't hesitate to Google or super search for any of that stuff for wider discussions and samples.

      Thanks. I usually find most things with a search, but sometimes the right search terms elude me. You know, you've got to know the answer before you can find it. :-)
Re: Location reference - programming style
by perlpie (Beadle) on Aug 14, 2010 at 22:30 UTC

    You could look in %INC to find where Location B might be. You'll need to slightly transform the B module name (use slashes instead of double colons and append .pm) to do the lookup. For some idea of what to expect...

    perl -MData::Dumper -e "print Dumper \%INC"

    gives

    $VAR1 = { 'warnings/register.pm' => '/System/Library/Perl/5.10.0/warni +ngs/register.pm', 'bytes.pm' => '/System/Library/Perl/5.10.0/bytes.pm', 'XSLoader.pm' => '/System/Library/Perl/5.10.0/darwin-thread- +multi-2level/XSLoader.pm', 'Carp.pm' => '/System/Library/Perl/5.10.0/Carp.pm', 'Exporter.pm' => '/System/Library/Perl/5.10.0/Exporter.pm', 'warnings.pm' => '/System/Library/Perl/5.10.0/warnings.pm', 'overload.pm' => '/System/Library/Perl/5.10.0/overload.pm', 'Data/Dumper.pm' => '/System/Library/Perl/5.10.0/darwin-thre +ad-multi-2level/Data/Dumper.pm' };
      Additionally: If it's module B that wants to know where its file is, you can make use of the __FILE__ token, but only from within the module itself (documented in perldata). That could be in a sub defined in that module which you can call from anywhere.

      Alternatively you could just not care where exactly the config file is stored, and just search for it yourself in @INC.

Re: Location reference - programming style
by CountZero (Bishop) on Aug 15, 2010 at 06:31 UTC
    Examine File::ShareDir::Install and File::ShareDir. These modules provide a portable way of installing (and more importantly) retrieving shared files, sich as config-files.

    No messing around with __FILE__ or @INC or relative filepaths, which one way or another will probably fail you in the end if your module gets installed on a system quite different from your own.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Location reference - programming style
by ikegami (Patriarch) on Aug 16, 2010 at 06:59 UTC
    use Cwd qw( realpath ); use File::Basename qw( dirname ); use lib dirname(realpath($0));