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

I'm running Perl 5.x on a Debian GNU/Linux system here, and wrote a simple script last night to normalize hundreds of filenames for me. A minor issue I've run into is with defining a directory path for the script to use. A snippet of relevant example code follows (slightly modified so that it makes sense without the rest of the script):

my $direct; chomp($direct = $ARGV[0]); chdir($direct);

Basically, this script as currently written forces me to use absolute paths, whereas I'd like to make it use relative paths. Best would be path relative to where I am in the filesystem when I run it, but it won't even recognize relative path from the location of the script, which just boggles my mind. What am I missing?

I've done searches at PerlMonks, looked through several books (including Visual Quickstart: Perl and CGI for the World Wide Web, the llama, and Perl in a Nutshell), and browsed through online tutorials, but haven't discovered anything particularly helpful on the matter.

- apotheon
CopyWrite Chad Perrin

Replies are listed 'Best First'.
Re: working with relative paths
by steves (Curate) on Oct 30, 2004 at 01:57 UTC

    Relative paths should work with chdir, being relative to where you are when you run (not where the script is). Example from a Solaris Perl 5.8 system:

    use strict; use Cwd; print "cwd [1] = ", cwd(), "\n"; chdir("/tmp"); print "cwd [2] = ", cwd(), "\n"; chdir("steve"); # relative! print "cwd [3] = ", cwd(), "\n";
    produces:
    cwd [1] = /export/home/foo cwd [2] = /tmp cwd [3] = /tmp/steve

      Maybe it "should" work (at least I think so), but the problem is that it doesn't. I'm beginning to wonder if it's some kind of system configuration issue. Is there any reason chdir() would work differently for a scalar variable than for hardcoded paths? Obviously, I'm trying to make a script that works for more than one filepath without having to rewrite the script every time.

      - apotheon
      CopyWrite Chad Perrin
        chdir has to work or I'll eat my hat, ;-) as it is one of the most fundamental functions. Perhaps if you posted a short but complete example, along with its actual output and the expected result, it would be easier to figure out what's going on.

        A couple of tricks that might help: use strict, warnings, and diagnostics; try chdir $direct or die $! to see if there is an error message.

Re: working with relative paths
by bobf (Monsignor) on Oct 30, 2004 at 04:00 UTC

    Take a look at File::Spec. It has quite a few very handy methods to portably manipulate paths, including abs2rel and rel2abs, which convert absolute paths to relative paths and visa versa. Unless I'm misunderstanding the problem, you should be able to use them to do what you need (it makes use of cwd if a base path is not supplied).

    HTH

      It turns out I just made a stupid, boneheaded error, actually, as fglock pointed out above. It looks like File::Spec will be of great use to me in the future, though. Thanks for the link.

      - apotheon
      CopyWrite Chad Perrin
Re: working with relative paths
by TedPride (Priest) on Oct 30, 2004 at 02:33 UTC
    Take a look at the following %ENV variables:

    SCRIPT_NAME : /cgi-local/env.pl
    DOCUMENT_ROOT : /u/web/folder
    SCRIPT_FILENAME : /u/web/folder/cgi-bin/env.pl

    You can use these to start your absolute path, rather than having to enter it by hand, and all you have to do from there is keep track of the current folder with a little creative programming.

      This isn't for a website, and I'm not using a cgi-bin. In fact, I don't have any kind of web server installed on this system. I'm just writing Perl on it for system administration tasks, mostly.

      - apotheon
      CopyWrite Chad Perrin
Re: working with relative paths
by ccn (Vicar) on Oct 30, 2004 at 20:05 UTC
    Does this help?
    use vars qw($Bin $Script); BEGIN { ($Bin, $Script) = split /([^\/\\]+)$/, $0 } chdir $Bin . $ARGV[0];

      Changing the way I used opendir() helped, actually. See above discussion for details.

      - apotheon
      CopyWrite Chad Perrin
      use vars qw($Bin); BEGIN { $Bin = qx(pwd) } chdir $Bin . $ARGV[0];

      .{\('v')/}
      _`(___)' __________________________
      Wherever I lay my KNOPPIX disk, a new FREE LINUX nation could be established.