Ответ 1
Стандартный FindBin
модуль делает то, что вы хотите.
use FindBin;
use lib "$FindBin::Bin/../lib";
perldoc FindBin
для более.
У меня есть dir foo
, и у меня есть lib
и bin
. Скрипты в bin
нуждаются в материалах в lib
. Я делаю что-то вроде этого:
#!perl
use strict;
use warnings;
use lib '../lib';
use Foo; # <-- comes from lib
Но это означает, что я должен быть в директории bin
для запуска script. Конечно, есть лучший способ. Каков правильный способ сделать это?
Стандартный FindBin
модуль делает то, что вы хотите.
use FindBin;
use lib "$FindBin::Bin/../lib";
perldoc FindBin
для более.
Проведите полный путь к вашему .pl
через __FILE__
, а затем нажмите ../lib
в конце или выскочите последний элемент split(/\//,__FILE__)
и добавьте /lib
к этому.
Модуль "FindBin" будет работать только в том случае, если каталог, в котором находится perl script, находится в вашей системе PATH, иначе он потерпит неудачу. Чтобы преодолеть этот, вы можете манипулировать значением $0
, чтобы получить информацию о своем пути к perl-модулю и передать значение use lib
.
Что-то вроде этого -
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: Модуль FindBin работает отлично и может быть использован, как описано в Майкл, ответьте. Мое понимание его работы было неполным, и поэтому привело меня к тому, чтобы сделать первый комментарий, который я теперь отвлекаю. Во всяком случае, я не вижу причин, почему этот метод не должен работать, хотя и с несколькими строками, чем может быть достигнуто с помощью FindBin (TMTOWTDI).
Я обычно использую эту технику. Его печально вдохновили мои PHP-дни:
Его удобно в ситуациях, когда вы знаете, где данный файл будет относиться к текущему, и не уверены в точках входа, которые он может вызывать, или в окружающей среде во время вызова.
Однако я обычно использовал бы эту технику только для тестовых скриптов, которым нужны фиктивные библиотеки для эмуляции вещей.
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;
В идеале должен быть какой-то модуль где-то, который делает это, а если нет, то я получу соблазн написать один:
use Some::Module ();
use lib Some::Module::relative_self('../../lib', __FILE__ );
Мое решение:
use lib substr(__FILE__, 0, rindex (__FILE__, "/"));
Просто чтобы добавить свои собственные два цента в эту подборку ответов, я обычно решаю эту проблему, используя что-то в этих строках:
use lib do {
use Cwd 'realpath';
my ($dir) = __FILE__ =~ m{^(.*)/}; # $dir = path of current file
realpath("$dir/../lib"); # path of '../lib' relative to $dir
};
Мне нравится использовать блок do
, потому что все необходимое так аккуратно содержится в нем. Если вам когда-либо понадобится скопировать/вставить или попытаться понять ваш код позже, вам не придется искать отдельный блок BEGIN
или что-то в этом роде.
В приведенном выше коде наивно предполагается, что /
используется как разделитель dir/filename.
use lib './';
работает для меня с Perl v5.14.2 в linux box, чтобы включить файлы в тот же каталог, что и мой script.
Возможно, вам будет полезно перемещать каталоги lib и bin в рабочем каталоге script и пытаться ссылаться на них с помощью
use lib './bin/';
Как насчет:
BEGIN: {
push @INC, '/full/path/to/lib';
}
Для выполнения относительной ссылки предполагается, что вы сохраните ее в каталоге bin, поэтому вместо этого вставьте вместо нее относительную ссылку.