Как загрузить библиотеки относительно местоположения скрипта в Perl? - PullRequest
0 голосов
/ 01 октября 2010

Как вы можете получить текущий каталог скриптов в Perl?

Это должно работать, даже если скрипт импортирован из другого скрипта (require).

Это не текущий каталог

Пример:

#/aaa/foo.pl
require "../bbb/foo.pl"

#/bbb/bar.pl
# I want to obtain my directory (`/bbb/`)
print($mydir)

Сценарий foo.pl может быть выполнен любым способом и из любого каталога, например perl /aaa/foo.pl или ./foo.pl.

Ответы [ 6 ]

4 голосов
/ 01 октября 2010

Люди обычно делают

use FindBin '$Bin';

и затем используйте $Bin в качестве базового каталога запущенного скрипта. Тем не менее, это не будет работать, если вы делаете такие вещи, как

do '/some/other/file.pl';

, а затем ожидайте, что $Bin будет содержать /some/other/ в этом. Я уверен, что кто-то думал о чем-то невероятно умном, чтобы обойти это, и вы найдете это где-нибудь на CPAN, но лучшим подходом может быть не включение программы в программу, а использование замечательных способов повторного использования кода Perl, намного лучше, чем do и подобные конструкции. Модули, например.

Обычно их не должно волновать, из какого каталога они были загружены. Если им действительно нужно действовать по какому-то пути, вы можете просто передать им этот путь.

2 голосов
/ 02 октября 2010

См. Dir::Self CPAN модуль.Это добавляет псевдо-константу __DIR__ к комплименту __FILE__ & __LINE__.

use Dir::Self;

use lib __DIR__ . '/lib'; 
1 голос
/ 01 октября 2010

От ответа perlfaq8 на Как добавить каталог, в котором находится моя программа, к пути поиска модуля / библиотеки?


(предоставлено Брайаном Д. Фой)

Если вы уже знаете каталог, вы можете добавить его в @INC, как и для любого другого каталога. Вы можете, если вы знаете каталог во время компиляции:

use lib $directory;

Хитрость в этой задаче - найти каталог. Прежде чем ваш скрипт сделает что-то еще (например, chdir), вы можете получить текущий рабочий каталог с помощью модуля Cwd, который поставляется с Perl:

BEGIN {
    use Cwd;
    our $directory = cwd;
    }

use lib $directory;

Вы можете сделать аналогичную вещь со значением $ 0, которое содержит имя скрипта. Это может содержать относительный путь, но rel2abs может превратить его в абсолютный путь. Как только у вас есть

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

    my $path   = rel2abs( $0 );
    our $directory = dirname( $path );
    }

use lib $directory;

Модуль FindBin, который поставляется с Perl, может работать. Он находит каталог текущего запущенного скрипта и помещает его в $ Bin, который затем можно использовать для построения правильного пути к библиотеке:

use FindBin qw($Bin);

Вы также можете использовать local :: lib, чтобы сделать то же самое. Установите модули, используя настройки local :: lib, затем используйте модуль в вашей программе:

 use local::lib; # sets up a local lib at ~/perl5

Более подробную информацию смотрите в документации local :: lib.

1 голос
/ 01 октября 2010

Извините за остальные 4 ответа, но ни один из них не сработал, вот решение, которое действительно работает.

В приведенном ниже примере, который добавляет каталог lib для включения пути, $dirname будет содержать путь к текущему сценарию. Это будет работать, даже если этот скрипт включен с использованием require из другого каталога.

BEGIN {
   use File::Spec;
   use File::Basename;
   $dirname = dirname(File::Spec->rel2abs( __FILE__ )) . "/lib/";
}
use lib $dirname;
1 голос
/ 01 октября 2010

Я использую этот фрагмент очень часто:

   use Cwd qw(realpath);
   use File::Basename;

   my $cwd = dirname(realpath($0));

Это даст вам реальный путь к каталогу, содержащему текущий запущенный скрипт. «реальный путь» означает все символические ссылки, «.» и ".." решено.

0 голосов
/ 01 октября 2010

Допустим, вы ищете script.pl. Вы можете запустить его, или вы могли включить его. Вы не знаете Так что он либо лежит в таблице %INC в первом случае, либо как $PROGRAM_NAME (он же $0) во втором.

use strict;
use warnings;
use English qw<$PROGRAM_NAME>;    
use File::Basename qw<dirname>;
use File::Spec;
use List::Util qw<first>;

# Here we get the first entry that ends with 'script.pl'
my $key  = first { defined && m/\bscript\.pl$/ } keys %INC, $PROGRAM_NAME;
die "Could not find script.pl!" unless $key;
# Here we get the absolute path of the indicated path.
print File::Spec->rel2abs( dirname( $INC{ $key } || $key )), "\n";

Ссылка на File::Basename, File::Spec и List::Util

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...