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

First, I'm new to Perl (among other things!). This may be a naive question, but I have yet to find a conclusive answer. If there is a simple answer (anyone), please enlighten me.

The form of relative path strings seems to me to vary from code to code, coder to coder with regard to placement of delimiters.

Eg:
1. /dir/dir/
2. /dir/dir
3. dir/dir/
4. dir/dir

For my own internal uses I prefer the No 3 form. It seems to make things simpler? But with Perl (i.e File::Spec) & other library calls I have to massage the strings into shape a lot of the time.

Is one of the forms a 'better' way? More portable? More accepted? More Perl?

Replies are listed 'Best First'.
Re: Path strings
by bobf (Monsignor) on Jan 27, 2007 at 04:35 UTC

    If you're asking how to portably manipulate path names, File::Spec is the answer. I'm not sure what you mean by needing to "massage the strings into shape" - could you give us an example? Perhaps you haven't found the right method to make things easier.

    Update: I missed the emphasis on relative path names in the OP. To build upon my original answer, note that File::Spec has two methods that you might find useful: abs2rel and rel2abs.

      When I use File::Spec->splitpath() the final directory is seen as a file unless it has a trailing delimiter, in which case it is seen as part of the directory. Also the doc on the module states "The directory portion may or may not be returned with a trailing '/'".

      When I use File::Basename->parsefile() the final directory is seen as a suffix unless it has a trailing delimiter, in which case it is seen as part of the directory.

      Also when incorporating other peoples code, this situation crops up.

      When I say "massage", I mean I must add and remove the delimiters from the strings to split them, join them, pass them on etc.

        If you're using splitpath to split a path that ends in a directory rather than a file, then you should be using splitdir instead*. That may solve your trailing '/' issue.

        I don't think I've ever had to manually add or remove delimiters from paths (with or without filenames) when using File::Spec. If you have specific examples that cause you to jump through hoops, please post them. I'm sure the monks around here will provide several approaches to solving the problem. :-)

        *Update: You could use splitpath, but you would need to set the second param to true (or, as you found, add a trailing directory separator). See the docs for more info.

      When I run:,

      my $curdir = File::Spec->rel2abs(File::Spec->curdir());

      I am returned an absolute path without a trailing delimiter, which I would expect (like) to see.

        A quick look at the source code shows that rel2abs (like many of the functions in File::Spec) calls canonpath. One of the things that function does is remove the trailing delimiter. According to the docs (for catdir, as it turns out), this is because

        it doesn't look good, isn't necessary and confuses OS/2

        I am not as familiar with the functions in Cwd, but after looking at the docs and source code it also appears to leave off the trailing delimiter.

        If you really want a trailing delimiter, then you may have to add it yourself. Sorry. :-)

Re: Path strings
by liverpole (Monsignor) on Jan 27, 2007 at 04:38 UTC
    Your question isn't really related to Perl; it's more of a Unix/Linux question.

    In the examples you gave:

    1. /dir/dir/ 2. /dir/dir 3. dir/dir/ 4. dir/dir

    Numbers 1 and 2 are absolute paths, meaning that they start at (ie. "are anchored at") the root directory "/".

    Numbers 3 and 4 and relative paths, meaning that there location depends on which directory you are in when you refer to them.  For example, if you are in the absolute directory "/var/www/html", and you refer to "css/styles", you are accessing the absolute directory "/var/www/html/css/styles".

    But if you started in the directory "/var/www/cgi", then referring to "css/styles" would mean an absolute path of "/var/www/cgi/css/styles" instead.

    Other than that, "/dir/dir/" and "/dir/dir" are nearly always identical.  There are a few places where they behave in subtly different ways (eg. if "/dir/dir" is a symbolic link), but they are not anything you need to worry about at this stage in your learning curve.


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/

      This was my understanding, outside of the symbolic link meaning, which I have yet to think about or delve into.

      See my other replies.