如何从相对位置使用Perl模块?

时间:2021-11-26 07:12:27

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:

我有一个名为foo的目录,并且我有lib和bin。 bin中的脚本需要lib中的东西。我做这样的事情:

#!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?

但这意味着我必须在bin目录中运行脚本。当然有更好的方法。什么是正确的方法呢?

8 个解决方案

#1


48  

The standard FindBin module does what you want.

标准的FindBin模块可以满足您的需求。

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

perldoc FindBin for more.

perldoc FindBin了解更多。

#2


5  

Parse out the complete path to your .pl via __FILE__ and and tack the ../lib on the end or pop off the last element of split(/\//,__FILE__) and add /lib to that.

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

#3


3  

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

我通常使用这种技术。从我的PHP时代中受到启发:

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__ ); 

#4


3  

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.

“FindBin”模块仅在perl脚本所在的目录位于系统PATH中时才有效,否则将失败。为了克服这个问题,您可以操作$ 0值来获取路径到perl模块的信息,并传递值以使用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).

编辑:FindBin模块工作得非常完美,可以按照Michael的回答中的描述使用。我对它的工作原理的理解是不完整的,因此引导我做出我现在撤回的第一个评论。无论如何,我没有看到任何理由为什么这个方法不应该工作,尽管比使用FindBin(TMTOWTDI)可以实现的更多行。

#5


0  

My solution:

我的解决方案

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

#6


0  

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.

我喜欢使用do块,因为所需的一切都整齐地包含在其中。如果您需要复制/粘贴,或者稍后尝试理解您的代码,则不必寻找单独的BEGIN块或类似的东西。

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

上面的代码天真地假设/被用作目录/文件名分隔符。

#7


0  

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.

我一直在使用Perl v5.14.2在Linux机箱上工作,将文件包含在与我的脚本相同的目录中。

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

也许你可以将你的lib和bin目录移动到脚本的工作目录下并尝试使用它们来引用它们

use lib './bin/';

#8


-3  

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.

要做一个相对引用会假设你要将它保存在bin目录中,所以要在那里插入相对引用。

#1


48  

The standard FindBin module does what you want.

标准的FindBin模块可以满足您的需求。

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

perldoc FindBin for more.

perldoc FindBin了解更多。

#2


5  

Parse out the complete path to your .pl via __FILE__ and and tack the ../lib on the end or pop off the last element of split(/\//,__FILE__) and add /lib to that.

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

#3


3  

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

我通常使用这种技术。从我的PHP时代中受到启发:

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__ ); 

#4


3  

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.

“FindBin”模块仅在perl脚本所在的目录位于系统PATH中时才有效,否则将失败。为了克服这个问题,您可以操作$ 0值来获取路径到perl模块的信息,并传递值以使用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).

编辑:FindBin模块工作得非常完美,可以按照Michael的回答中的描述使用。我对它的工作原理的理解是不完整的,因此引导我做出我现在撤回的第一个评论。无论如何,我没有看到任何理由为什么这个方法不应该工作,尽管比使用FindBin(TMTOWTDI)可以实现的更多行。

#5


0  

My solution:

我的解决方案

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

#6


0  

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.

我喜欢使用do块,因为所需的一切都整齐地包含在其中。如果您需要复制/粘贴,或者稍后尝试理解您的代码,则不必寻找单独的BEGIN块或类似的东西。

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

上面的代码天真地假设/被用作目录/文件名分隔符。

#7


0  

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.

我一直在使用Perl v5.14.2在Linux机箱上工作,将文件包含在与我的脚本相同的目录中。

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

也许你可以将你的lib和bin目录移动到脚本的工作目录下并尝试使用它们来引用它们

use lib './bin/';

#8


-3  

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.

要做一个相对引用会假设你要将它保存在bin目录中,所以要在那里插入相对引用。