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

Dear Monks,
Background:
I've never before bothered to make any of my code platform independent. Linux has been my predominant work platform for 8 years now. However I've recently started playing around on Windows, so have decided to explore creating code that is more platform independent.

I found the below code snippit to determine the parent directory of a script in one of my codebases:
use Cwd qw(abs_path); use File::Basename qw(dirname); my $dir_parent = abs_path(dirname(__FILE__) . '/../');
Now there is nothing inherently bad with this code. However, it hard-codes both the path separator and the .. parent directory alias. I therefore whipped out File::Spec , and come up with this monstrosity.
use File::Spec; my $dir_parent = do { my ($vol, $dir, $file) = File::Spec->splitpath( File::Spec->rel2abs(__FILE__) ); # Go up 1 directory my @dirs = File::Spec->splitdir($dir); pop @dirs while (@dirs > 1 && $dirs[-1] eq ''); # Clean up pop @dirs if @dirs > 1; # Go up 1 real directory. $dir = File::Spec->catdir(@dirs); File::Spec->catpath($vol, $dir); };
Now this code is nice in a way as it only relies on File::Spec. But, god! It's soo long!

I've therefore decided to assume that '..' is a platform specific reference. That leaves me currently with the following code:
use File::Basename qw(dirname); use File::Spec; my $dir_parent = File::Spec->rel2abs( File::Spec->catdir( dirname(__FILE__), '..' ) );
Now, I've since adapted my code to no longer need this information. However, the above two questions still remain. How would y'all determine the parent directory of a script or module in a platform independent way?

Regards,
- Miller

PS

Replies are listed 'Best First'.
Re: Platform Independent Directory Traversal
by RMGir (Prior) on Jul 29, 2007 at 10:39 UTC
    Answering the other half of your question, no, "." and ".." aren't cross platform.

    For example, on vms, it's "[]" and "[-]".

    See File::Spec::VMS for more examples, or File::Spec::Mac for "Classic" MacOS, where it was ":" and "::"...


    Mike
Re: Platform Independent Directory Traversal
by Anonymous Monk on Jul 29, 2007 at 04:19 UTC
    RTFM
    Returns a string representation of the parent directory. 
        $updir = File::Spec->updir();
    
      I was aware of this function from File::Spec, but misunderstood what it meant. Since it did not accept any arguments, I assumed (without testing) that it would simply return the "parent directory" of the "current working directory". Instead it returns '..'.

      This means that my final solution could be simplified to:
      use File::Basename qw(dirname); use File::Spec; print File::Spec->rel2abs( File::Spec->catdir( dirname(__FILE__), File::Spec->updir(), ) );
      However, is this right? Is this how the updir() function was intended to be used? I've probably just been ruminating on the problem for too long. But this solution still somewhat bothers me.

      Also, I appreciate the RTFM reference in the spirit in which it was given. However, the acronym itself is rather rude, and often plays on false assumptions.

      Thanks again,
      - Miller

        Your example code looks like what I usually use. I prefer File::Spec::Functions sometimes, but it seems workable to me.

        print File::Spec->rel2abs( File::Spec->catdir( dirname(__FILE__), File::Spec->updir(), ) );
        Bah, that is ugly! I'd do it another way.

        Did you know that rel2abs takes an optional second parameter, the reference directory? So, a much cleaner way (IMO) to do this is:

        print File::Spec->rel2abs( File::Spec->updir, dirname(__FILE__) );
        Even though you probably can just do
        print dirname(dirname(File::Spec->rel2abs(__FILE__)));
        You may probably even drop the rel2abs call, in this specific case, as __FILE__ would appear to return an absolute path – even though I don't quite trust that to always be the case.
        print dirname(dirname(__FILE__)); # ?? Is this reliable?

        All code snippets, mine and yours, show the same string in my test.