NAME
Path::Class::Tiny - a Path::Tiny wrapper for Path::Class compatibility
VERSION
This document describes version 0.06 of Path::Class::Tiny.
SYNOPSIS
use Path::Class::Tiny;
# creating Path::Class::Tiny objects
$dir1 = path("/tmp");
$dir2 = dir("/home");
$foo = path("foo.txt");
$foo = file("bar.txt");
$subdir = $dir->child("foo");
$bar = $subdir->child("bar.txt");
# stringifies as cleaned up path
$file = path("./foo.txt");
print $file; # "foo.txt"
# reading files
$guts = $file->slurp;
@lines = $file->slurp;
# writing files
$bar->spew( $data );
$bar->spew( @data );
# comparing files
if ( $foo->ef($bar) ) { ... }
# reading directories
for ( $dir->children ) { ... }
DESCRIPTION
What do you do if you started out (Perl) life using Path::Class, but then later on you switched to Path::Tiny? Well, one thing you could do is relearn a bunch of things and go change a lot of existing code. Or, another thing would be to use Path::Class::Tiny instead.
Path::Class::Tiny is a thin(ish) wrapper around Path::Tiny that (mostly) restores the Path::Class interface. Where the two don't conflict, you can do it either way. Where they do conflict, you use the Path::Class way. Except where Path::Class is totally weird, in which case you use the Path::Tiny way.
Some examples:
Creating file/dir/path objects
Path::Class likes you to make either a file
object or a dir
object. Path::Tiny says that's silly and you should just make a path
object. Path::Class::Tiny says you can use any of the 3 words you like; all the objects will be the same underneath.
my $a = file('foo', 'bar');
my $b = dir('foo', 'bar');
my $c = path('foo', 'bar');
say "true" if $a eq $b; # yep
say "true" if $b eq $c; # also yep
Going up or down the tree
Again, both styles work.
my $d = dir("foo");
my $up = $d->dir; # this works
$up = $d->parent; # so does this
$up = $d->dir->parent; # sure, why not?
my $down = $d->child('bar'); # Path::Tiny style
my $down = $d->subdir('bar'); # Path::Class style
Slurping files
This mostly works like Path::Class, in that the return value is context-sensitive, and options are sent as a hash and not as a hashref.
my $data = $file->slurp; # one big string
my @data = $file->slurp; # one element per line
my @data = $file->slurp(chomp => 1); # chomp every line
my @data = $file->slurp(iomode => '<:crlf'); # Path::Class style; works
my @data = $file->slurp(binmode => ':crlf'); # vaguely Path::Tiny style; also works
my @data = $file->slurp({binmode => ':crlf'}); # this one doesn't work
my $data = $file->slurp(chomp => 1); # neither does this one, because it's weird
DETAILS
This module is still undergoing active development. While the general UI is somewhat constrained by the design goals, specific choices may, and almost certainly will, change. I think this module can be useful to you, but for right now I would only use it for personal scripts.
A Path::Class::Tiny isa
Path::Tiny, but not isa
Path::Class::Entity. At least not currently.
Path::Class::Tiny is not entirely a drop-in replacement for Path::Class, and most likely never will be. In particular, I have no interest in implementing any of the "foreign" methods. However, it should work for most common cases, and, if it doesn't, patches are welcome.
Performance of Path::Class::Tiny should be comparable to Path::Tiny. Again, if it's not, please let me know.
PATH::CLASS STYLE METHODS
cleanup
Redirects to "canonpath" in Path::Tiny.
components
Basically just like components
from Path::Class::Dir, which means that it accepts offset and length arguments (which Path::Class::File doesn't). Another nice difference: calling components
from Path::Class::File in scalar context doesn't do anything useful, whereas Path::Class::Tiny always returns the number of components, which is (hopefully) what you expect.
The only real difference between Path::Class::Tiny's components
and Path::Class::Dir's components
is that you don't get the volume returned in the Path::Class::Dir version. In this version, the volume (if any) will just be part of the first component in the list.
dir_list
Just an alias for "components", so it also works on files (Path::Class::File doesn't have a dir_list
method). This means the basename is always the last entity in the list, even for files. Basically this is just here for compatibility's sake, and you probably shouldn't use it for new code, because the name doesn't really sound like what it does.
next
Uses "iterator" in Path::Tiny (with its default value of no recursion) to implement the interface of next
from Path::Class::Dir. The primary difference this engenders is that the Path::Class::Dir version will return .
and ..
, whereas this version will not. I also don't guarantee this version is re-entrant.
rmtree
Just an alias to "remove_tree" in Path::Tiny.
subdir
Just an alias to "child" in Path::Tiny.
touch
Basically just calls "touch" in Path::Tiny, which is better than "touch" in Path::Class::File in a couple of ways:
It returns the path object, which is useful for chaining.
It takes an argument, so you can set the time to something other than "now."
However, Path::Class::Tiny::touch
is even better than that! It adds another cool feature:
If the argument is an object, and that object has an
epoch
method, it will call it and pass the result on toPath::Tiny::touch
.
The practical result is that your argument to touch
can be an integer (number of epoch seconds), or any of the most popular datetime objects: DateTime, Time::Piece, Time::Moment, Date::Easy, and possibly others as well.
Potential Incompatibility: The only way these additional features could be incompatible with existing Path::Class
code is if it were relying on the return value from touch
, which in Path::Class
is either the return from open
or the return from utime
(so theoretically it's true if the touch
was successful and false otherwise). Path::Tiny
(and thus Path::Class::Tiny
) will instead throw an exception if the touch
was unsuccessful and return the chained object.
copy_to
Just an alias to "copy" in Path::Tiny.
move_to
There are two big differences between "move" in Path::Tiny and "move_to" in Path::Class::File:
On failure,
Path::Class::File::move_to
returns undef, whilePath::Tiny::move
throws an exception.On success,
Path::Tiny::move
just returns true.Path::Class::File::move_to
, on the other hand, returns the path object for chaining, which has been modified to have the new name.
Path::Class::Tiny
splits the difference by throwing an exception on error, and returning the modified $self
on success. That means this method is a mutator! Consequently, use of this method means your objects are not immutable. No doubt many people will object to this behavior. However, after some internal debate, it was decided to retain this aspect of Path::Class's interface for the following reasons:
It keeps from breaking existing
Path::Class
code that you're trying to convert over toPath::Class::Tiny
. While we do implement some breaking changes, most of them feel a lot less likely to be encountered in real code than this one.The real-world thing that the object represents--that is, the file on disk--is itself being mutated. If the object is not changed to reflect the new reality, then any stray copies of it lying around now reference a file that doesn't exist. So it seems just about as likely to fix a problem as to cause one.
If you don't like the mutability, just call "move" instead.
PATH::TINY STYLE METHODS
Since a Path::Class::Tiny
object isa
Path::Tiny object, the vast majority of Path::Tiny
methods just work the same way they always have. Notable methods (with exceptions or just clarifications) are listed below.
move
Unchanged from Path::Tiny, which means it's quite different from "move_to". In particular, move
does not mutate the object, which means that code like this:
my $file = path($whatever);
$file->move($new_name);
say $file->basename;
does not give you the basename of the file-as-it-is, but rather the basename of the file-as-it-was, which could be considered less useful. But at least it doesn't mutate the object, so it's got that going for it. If you actually want the object to be mutated, try "move_to" instead.
tempfile
Basically works just like "tempfile" in Path::Tiny, except it:
is exported whether you like it or not.
can't be called as a class method, only a global function.
returns a Path::Class::Tiny instead of a Path::Tiny (obviously).
Other than that, it retains all the coolness of Path::Tiny::tempfile
, including the normalization of arguments, the handling of template as either named or positional argument, and the addition of TMPDIR => 1
as a default (which you can override).
tempdir
Everything discussed re "tempfile" applies to "tempdir" as well. Don't forget that if you want to keep a tempfile
, you have to pass UNLINK => 0
, whereas if you want to keep a tempdir
, you have to pass CLEANUP => 0
. That's not our fault (nor Path::Tiny's neither): talk to File::Temp about it.
NEW METHODS
dirname
Since dirname
in Path::Tiny is stupid, and dirname
in Path::Class doesn't even exist, dirname
in Path::Class::Tiny is just an alias for parent
, on the grounds that that's almost certainly what you wanted anyway.
ef
Are you tired of trying to remember which method (or combination of methods) you have to call to verify that two files are actually the same file, where one path might be relative and the other absolute, or one might be a symlink to the other, or one might be a completely different path but one directory somewhere in the middle is really a symlink to a directory in the middle of the other path so they wind up being the same path, really? Yeah, me too. In bash
, this is super easy:
if [[ $file1 -ef $file2 ]]
Well, why shouldn't it be easy in Perl too? Okay, now it is:
my $file1 = path($whatever);
if ( $file1->ef($file2) )
While $file1
must obviously be a Path::Class::Tiny, $file2
can be another Path::Class::Tiny object, or a Path::Class::Entity, or a Path::Tiny, or just a bare string. Most anything should work, really. Do note that both files must actually exist in the filesystem though. It's also okay for both to be exactly the same object:
if ( $file1->ef($file1) ) # always true
mtime
This is mostly just a shortcut for going through stat
, but it has the added benefit of producing a Date::Easy::Datetime object. Thus:
my $file = path($whatever);
$file->mtime == $file->stat->mtime # true, but maybe not for the reason you thought
$file->mtime->epoch == $file->stat->mtime # true, and more reflective of reality
$file->mtime->isa('Date::Easy::Datetime') # true, which can be handy:
say $file->mtime->as('-Ymd') # day portion of mtime, in YYYY-mm-dd format
say "file is from the future!" # this one will work, but only if you have
if $file->mtime > now; # previously done `use Date::Easy` (to get `now`)
Note that Date::Easy::Datetime
is loaded on demand, so:
It is not necessary for you to load it ahead of time.
However, as the example above mentions, you don't get all the exports you would if you
use Date::Easy
, so you may wish to do that anyway.If Date::Easy is not installed, you get a runtime error when you call
mtime
.
SUPPORT
Perldoc
You can find documentation for this module with the perldoc command.
perldoc Path::Class::Tiny
Bugs / Feature Requests
This module is on GitHub. Feel free to fork and submit patches. Please note that I develop via TDD (Test-Driven Development), so a patch that includes a failing test is much more likely to get accepted (or at least likely to get accepted more quickly).
If you just want to report a problem or suggest a feature, that's okay too. You can create an issue on GitHub here: https://github.com/barefootcoder/path-class-tiny/issues.
Source Code
none https://github.com/barefootcoder/path-class-tiny
git clone https://github.com/barefootcoder/path-class-tiny.git
AUTHOR
Buddy Burden <barefootcoder@gmail.com>
COPYRIGHT AND LICENSE
This software is Copyright (c) 2021 by Buddy Burden.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)