Let Paths Be Paths Again

The de facto standard way of constructing portable filesystem paths in Perl is through the use of File::Spec's catfile and catdir functions. Example:

my $path = File::Spec->catfile('dir', 'subdir', 'file.txt');

This method, or a similar one involving Path::Class, is the most recommended approach and has been adopted by application development frameworks like Dancer (which has a wrapper method for it, named path) and Catalyst (with its path_to method).

The slight problem that I see with this method is that it makes code a bit more complicated, and thus a bit less readable. Paths become lists of parameters and no longer look like paths.

I wrote a simple module that tries to address this by allowing you to write paths the traditional way -- as strings, using a directory separator of your choice (/ being the default), while the catfile stuff happens behind the scenes. You can just say:

my $path = path 'dir/subdir/file.txt';

What it does is it splits the path string on each occurrence of the forward slash and feeds the resulting list of path components to File::Spec->catfile, which reassembles them using the appropriate OS-specific directory separator, and constructs the OS-specific path that you want.

The module is up on Github, and should also be available on CPAN shortly.


I'm pretty sure this exists already, although for the life of me I can't recall a specific module name.

I know that I've personally written it as a utility function within some larger module four or five times.

(The one from File::PathList looks closest)

Using Path::Class is just as readable IMHO.

I'm genuinely curious: which currently-used systems don't use Unix-style paths? VMS? Windows seems to accept them in most contexts, and I don't think anyone uses Mac OS 9 anymore. It would be great to finally stop having to code defensively around paths (the runner-up bane of programmers' existence, after "\n" vs. "\r\n" vs. "\r").

I like the concept, but I worry a little about the way the separator is stored. If two modules both use File::PlainPath, and both use a different seperator, will they interfere with each other over the course of execution?

But what about absolute paths? What about drive letters? This doesn't take into account a lot of things that File::Spec does…

I'm with educated_foo on this one. 99,99% of the time, I've never bothered to use File::Spec and hardcode "/". IIRC, I've never had a CPAN Testers report where my modules fail because of path separator problem.

Majority convention becomes de facto standard all the time.

I ask because my main reasons for using Path::Class or File::Spec would be fear, uncertainty, and doubt. Where, and how often, will blindly using a Unix path cause trouble?

BTW, I'm not too worried about showing paths to users, since if they're not on Unix, they probably won't understand them. I have never, while using a Mac, had to deal with the colon-separated native paths.

"Where, and how often, will blindly using a Unix path cause trouble?"

Windows. it works *most* of the time. except sometimes it doesn't. and it probably won't be clear why.

(i speak from horrible experience here, having lost a couple of hours last month debugging a problem where some paths in a configuration file were Unix-style and worked just fine, and others were Unix-style and failed far down the line with obtuse error messages. comedy!)

Leave a comment

About Michał Wojciechowski

user-pic I blog about Perl.