Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Shlomi Fish (918)

Shlomi Fish
  shlomif@iglu.org.il
http://www.shlomifish.org/
AOL IM: ShlomiFish (Add Buddy, Send Message)
Yahoo! ID: shlomif2 (Add User, Send Message)
Jabber: ShlomiFish@jabber.org

I'm a hacker of Perl, C, Shell, and occasionally other languages. Perl is my favourite language by far. I'm a member of the Israeli Perl Mongers, and contribute to and advocate open-source technologies. Technorati Profile [technorati.com]

Journal of Shlomi Fish (918)

Thursday April 03, 2008
03:15 PM

How to Best Process the Directory Components of a Path

[ #36049 ]

This is cross-posted here from Israel.pm where I have yet to receive an answer.

I'm trying to process the directory components of a path (as an array) so that:

  1. It will be portable. (Work on Unix, Windows, VMS, etc.)
  2. It will keep the rest of the path components (if any) identical.
  3. It will work on both relative and absolute paths.

If the processing is to keep only the directories after "long-dir" then:

UNIX : /hello/there/long-dir/another/myfile.txt ==> another/myfile.txt
DOS : C:\Hello\There\Long-Dir\Another\myfile.txt ==> another\myfile.txt

UNIX: ./hi/long-dir/another/myfile.txt ==> another/myfile.txt
DOS: .\hi\long-dir\another\myfile.txt ==> another\myfile.txt

To do this I turned to File::Spec and File::Basename and wrote the following code which seems insanely complicated. I marked the place where I do the actual processing using a callback:

use File::Spec;
use File::Basename;

sub _process_filename_dirs
{
    my ($self, $fn, $callback) = @_;

    my $basename = basename($fn);
    my $dirpath  = dirname($fn);

    my ($volume, $directories, $filename) = File::Spec->splitpath($dirpath,
1);

    # The actual manipulation.
    my $dirs = $callback->([File::Spec->splitdir($directories)]);

    my $final_dir =
        File::Spec->catpath(
            $volume, File::Spec->catdir(@$dirs), $filename
        );

    if ($final_dir eq "")
    {
        return $basename;
    }
    else
    {
        return File::Spec->catfile(
            $final_dir, $basename
        );
    }
}

And so far I checked it works only on UNIXes (Linux in my case) and on relative paths.

So my questions are:

  1. Is there a simpler way to do it?
  2. Do Path-Class or File-Fu or a different abstraction provide an easier way to do it?
  3. Is it still buggy?

I should note that this hairiness is not limited to Perl. Common Lisp has a built-in portable path-manipulation abstraction that's also relatively complicated. See the "File and File I/O Chapter" and the a Portable Pathname library chapter

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • I'm not confident that I've understood your question correctly, but it seems like File::Spec->abs2rel() would do most of the work for you.