简体   繁体   中英

How do I use a Perl module from a relative location?

I have a dir called foo , and in that I have lib and bin . The scripts in bin need stuff in lib . I do something like this:

#!perl
use strict;
use warnings;
use lib '../lib';
use Foo; # <-- comes from lib

But that means I have to be in the bin dir to run the script. Surely there is a better way. What's the Right Way to do this?

The standard FindBin module does what you want.

use FindBin;
use lib "$FindBin::Bin/../lib";

perldoc FindBin for more.

通过__FILE__解析.pl的完整路径,并在../lib或弹出split(/\\//,__FILE__)的最后一个元素split(/\\//,__FILE__)并将/lib添加到该路径。

The "FindBin" module will only work if the directory that the perl script resides in is in your system PATH, else it will fail. To overcome that you can manipulate the $0 value to get your path-to-perl-module information and pass the value to use lib .

Something like this -

BEGIN {
    use File::Spec::Functions qw(rel2abs);
    use File::Basename qw(dirname);

    #Covert the script path to absolute and get its directory name
    our $path = dirname( rel2abs($0) );

    #Replace the bin tag with lib to get module directory
    $path =~ s{bin/?$}{lib};
}

use lib $path;

EDIT: The FindBin module works just perfectly and can be used as described in Michael's answer . My understanding of its workings was incomplete and so led me to making the first comment which I now retract. Anyway, I don't see any reason why this method shouldn't work albeit with a few more lines than could be achieved using FindBin (TMTOWTDI).

I generally use this technique. Its sadly inspired from my PHP days:

Its handy in situations where you know where a given file will be relative to the current one, and aren't sure of the entry points it may be called in or the surrounding environment at calltime.

However, I would generally use this technique only for test scripts which need dummy libraries for emulating things.

use File::Basename ();
use Cwd            ();
my $base_dir;
my $relative_path; 
BEGIN {
    $realitive_path = '../../' # Path to base of project relative to the current file
    $base_dir = Cwd::realpath( File::Basename::dirname(__FILE__) .'/' . $relative_path );
}


use lib "${base_dir}/lib";
use Foo;

Ideally there should be some module somewhere that does this, if not, I'm half tempted to write one:

use Some::Module ();
use lib Some::Module::relative_self('../../lib', __FILE__ ); 
use lib './';

has been working for me with Perl v5.14.2 on a linux box to include files in the same directory as my script.

Perhaps it would work for you to move your lib and bin directories under your script's working directory and try to reference them using

use lib './bin/';

我的解决方案

use lib substr(__FILE__, 0, rindex (__FILE__, "/"));

Just to add my own two cents to this collection of answers, I usually solve this problem using something along these lines:

use lib do {
    use Cwd 'realpath';
    my ($dir) = __FILE__ =~ m{^(.*)/};  # $dir = path of current file
    realpath("$dir/../lib");            # path of '../lib' relative to $dir
};

I like using a do block because everything needed is so neatly contained therein. If you ever need to copy/paste, or try to understand your code at a later time you don't have to look for a separate BEGIN block or anything like that.

The above code naïvely assumes that / is used as a dir/filename separator.

How about:

BEGIN: {
    push @INC, '/full/path/to/lib';
}

To do a relative reference would assume that you're going to keep it in the bin dir, so insert the relative reference there instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM