ccn has asked for the wisdom of the Perl Monks concerning the following question:

Sometimes I need to use modules which placed in the same directory where the script is. I can't write use lib qw(./lib); because the script can be called from any current working directory.

Now I write:

use vars qw($lib); BEGIN {$lib = $0; $lib =~ s/[^\/\\]+$//} use lib $lib . 'lib';

Can it be done better?

UPDATE: Thanks to Aristotle for the nice snippet

use File::Spec::Functions qw( rel2abs catdir ); use File::Basename; use lib catdir( dirname( rel2abs $0 ), 'lib' );

Replies are listed 'Best First'.
Re: use lib qw(relative path)
by davorg (Chancellor) on Sep 25, 2004 at 11:52 UTC

    Sounds like you need FindBin

    use FindBin qw($Bin); use lib "$Bin/lib";
    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      Hmmm.... It's solution but it is not appropriate for some hostings. I got fatal errors if I use FindBin qw($Bin $Script)

      opendir(/pub/home/****/cgi-bin/**/*****//../../../..): Permission deni +ed at /usr/libdata/perl/5.00503/FindBin.pm line 162 opendir(/pub/home/****/cgi-bin/**/*****//../../../..): Permission deni +ed at /usr/libdata/perl/5.00503/FindBin.pm line 163 Can't locate *****.pm in @INC (@INC contains: /lib /usr/local/lib/perl +5/site_perl/5.005/i386-freebsd /usr/local/lib/perl5/site_perl/5.005 . /usr/libdata/perl/5.00503/mach +/usr/libdata/perl/5.00503) at /pub/home/****/cgi-bin/**/*****/**.pl line 10.

      Now I write:

      use vars qw($Bin $Script); BEGIN { my $pos = rindex $0, '/'; $pos = rindex $0, "\\" if $pos == -1; if ($pos != -1) { $Bin = substr($0, 0, $pos); $Script = substr($0, $pos+1); } else { $Bin = '.'; $Script = $0; } } use lib "$Bin/lib";

      Can it be done better?

        I don't know whether your algorithm itself can be written in another way to make it better do FindBin's job, but you can make your algorithm more portable.

        If you want it to be portable you probably want to use File::Basename. Also, &File::Basename::dirname takes care of the special case of the argument being just a file with not directory in it, and returning ".". To continue being portable, use catfile instead of joining then strings with a slash.

        use File::Basename qw/ dirname basename /; use File::Spec::Functions qw/ catfile /; BEGIN { $Bin = dirname($0); $Script = basename($0); $Lib = catfile($Bin, 'lib'); } use lib $Lib;

        ihb

        Read argumentation in its context!

        I think it would be far more useful finding out why FindBin isn't working and spending time fixing that, rather than wasting time reimplementing it.

        We might be able to give you more help if there weren't so many ***s in your error messages :)

        --
        <http://www.dave.org.uk>

        "The first rule of Perl club is you do not talk about Perl club."
        -- Chip Salzenberg

      Yes, it is the solution. Thanks

Re: use lib qw(relative path)
by amonroy (Scribe) on Sep 25, 2004 at 21:26 UTC

    What about using the PERL5LIB environment variable? You wouldn't have to worry about doing use lib. You could do something like this to run your script:

    PERL5LIB=/path/lib;export PERL5LIB;/path/yourscript.pl

    Or you could do a shell script that would do that for you.

    ---
    -Andrés Monroy-Hernández

      Another thing you could try is:

      BEGIN{ use File::Basename; use File::Spec; my $dir = File::Spec->rel2abs(dirname($0)); die "Cannot relocate '$dir'.\n" unless(chdir($dir)); } use lib './lib';

      Regards,
      --
      -Andrés Monroy-Hernández

Re: use lib qw(relative path)
by Aristotle (Chancellor) on Sep 26, 2004 at 15:38 UTC

    I'd use amonroy's basic approach but without chdir and with less verbiage.

    use File::Spec::Functions qw( rel2abs catdir ); use File::Basename; use lib catdir( dirname( rel2abs $0 ), 'lib' );

    Update: s/basename/dirname/

    Makeshifts last the longest.

      s/basename/dirname/;

      Thanks, Aristotle. It's desired .