自作pmをuse libする

下にlibとかつくってそこにおいた自作pmをuseするとき、相対パスで呼び出してしまうと実行ディレクトリが違う場合(cronでまわしたりとか)に都合が悪かったりします。

そこで、以下のようにBEGINブロック内でスクリプト自身のパスをとってきてからuse libとかしてるんですが、このやり方おかしかったりしないんだろうか。もし、もっとこうした方がいいとかあればぜひお教え下さい。

├ main.pl
├ lib     
   â”” Hoge
      â”” Foo.pm
#!/usr/bin/perl

use strict;
use warnings;
use File::Basename;

my $w_dir;
BEGIN { $w_dir = dirname $ENV{_} }
use lib "$w_dir/lib";
use Hoge::Foo;

my $foo = Hoge::Foo->new("tester001");
print $foo->name;
package Hoge::Foo;
sub new {
    my $class = shift;
    my $name = shift;
    bless { name => $name } , $class;
}
sub name {
    my $self = shift;
    return $self->{name};
}
1;


追記(同日):

一部、記述を追加しました。


追記(3/7):

上記のようなことをやりたいんなら「$ENV{_}なんてものを使うより単に$0でいいじゃん」というのが自然な気がしてます。cronでまわすにしてもそれでできるわけだし。

use File::Basename;
my $w_dir;
BEGIN { $w_dir = dirname $0 }

みたいな感じで。

以下、コメントで教えていただいたものも紹介させていただきます。

use File::Basename;
use File::Spec;
my $w_dir;
BEGIN { $w_dir = dirname(File::Spec->rel2abs($0)); }

上記と同じような感じですが、常にフルパスを取得できるようにしています。

dirname $0だと./hoge.plで実行すると$w_dirに「.」が入り、/home/user/work/hoge.plで実行すると「/home/usr/work」が入りますが、上記のやり方だと常に「/home/user/work」が取得できますね。

もうひとつはFindBinモジュールを使うやり方。これだとFile::Basenameを使わずにFindBinだけでいけますね。

use FindBin;
my $w_dir;
BEGIN { $w_dir = $FindBin::Bin; }


追記(3/8):

さらにFindBin::libsを使えばlibを探してきてuse libしてくれます。超便利ですね!

use FindBin::libs;

名前の通り、デフォルトではlibを探しにいきます。他のディレクトリ名を指定すればそこをuse lib。

use FindBin::libs qw{ base=src print };

とやるとuse libしたディレクトリ一覧が以下のように標準出力されます。

Found */src:
        /home/webmaster/script/src
        /var/src


お答えいただいた方々、どうもありがとうございました。