Goodbye Path::Class, hello Path::Tiny

I like Path::Class, but it's clunky and slow. So I wrote Path::Tiny to scratch my itch.

It's smaller (roughly half the lines of code), comes in a single file, and is generally faster. Among other things, it has lots of handy UTF-8 input and output methods.

The downside is that it's less portable and less extensible, but let's be honest, most of us are developing only for Unix or Windows anyway. And when was the last time you subclassed Path::Class for something? I'll bet never. YAGNI.

Here's the synopsis:

use Path::Tiny;
# creating Path::Tiny objects
$dir = path("/tmp");
$foo = path("foo.txt");
$subdir = $dir->child("foo");
$bar = $subdir->child("bar.txt");
# reading files
$guts = $file->slurp;
$guts = $file->slurp_utf8;
@lines = $file->lines;
@lines = $file->lines_utf8;
$head = $file->lines( {count => 1} );
# writing files
$bar->spew( @data );
$bar->spew_utf8( @data );
# reading directories
for ( $dir->children ) { ... }
$iter = $dir->iterator;
while ( my $next = $iter->() ) { ... }

It does require a very new File::Spec that fixes some ugly, tricky bugs, but, otherwise, it's core only for any recent Perl.

Check it out!

Update: If you use Moose, there is also MooseX::Types::Path::Tiny.

Update 2: I didn't mention it before, but note that stringifying the Path::Tiny returns a (possibly cleaned up) copy of the original path.

This entry was posted in perl programming and tagged , , . Bookmark the permalink. Both comments and trackbacks are currently closed.


  1. Alexander Hartmaier
    Posted January 31, 2013 at 2:32 am | Permalink

    I wished you had improved Path::Class instead of releasing yet another module. This might need to refactor its internals completely but at least wouldn't require everybody to change their code.
    Its API is imho good but it lacks extensibility. I'd need support for various network devices like Cisco IOS routers and switches which file system starts with disk0:/, disk1:/ and flash:/.

    • Posted January 31, 2013 at 5:42 am | Permalink

      I did both, actually. See

      However, there are fundamental constraints in the design of Path::Class that limit how far it can be improved.

      Tiny modules are generally intended as 90% solutions to a problem. If you don't need the 100% solution, then you shouldn't have to pay the cost of the abstractions needed to deliver it. I'm intentionally not trying to write something that works for every filesystem for every device.

  2. Alexander Hartmaier
    Posted February 4, 2013 at 9:09 am | Permalink

    I've looked at the module now that it's on CPAN and some of its methodnames are suboptimal. For example I'd expect lines to return the number of lines not an array of lines. Is it too late to rename the method to slurp_lines?

    • Posted February 4, 2013 at 1:26 pm | Permalink

      Because lines() returns a map, if you call lines() in scalar context, you get the number of lines. (That could be clearer in the docs).

      Of course, for small files, it might be better to raw slurp the whole thing and run a regex on it for a count.

      Getting a line count (and throwing away the content in the process) seems like an unusual case, so having a method for that alone isn't appealing to me.

  3. Steffen Winkler
    Posted March 9, 2013 at 1:13 am | Permalink

    I wrote that "->parent->parent->parent" is ugly.
    "->parent(3)" or "->parents(3)" would solve that.

    "->child(@more)" allows more than 1 step, but the other direction "->parent" not.

One Trackback