NAME
Evo::Fs
VERSION
version 0.0405
SYNOPSIS
use Evo '-Fs; File::Basename fileparse';
my $fs = Evo::Fs->new(root => '/tmp/testfs');
say "/foo => ", $fs->path2real('/foo');
say "foo => ", $fs->path2real('/foo'); # the same
my $fh = $fs->open('foo/bar.txt', 'w'); # open and create '/foo' if necessary
$fs->close($fh);
$fs->write('a/foo', 'one'); # /tmp/test/a/foo
$fs->append('/a/foo', 'two'); # /tmp/test/a/foo
say $fs->read('a/foo'); # onetwo
say $fs->read('/a/foo'); # the same
# bulk
$fs->write_many('/a/foo' => 'afoo', '/b/foo' => 'bfoo');
# copying
$fs->write('/from/d/f' => 'OK');
# copy file
$fs->remove_tree('/to') if $fs->exists('/to');
$fs->copy_file('/from/d/f' => '/to/d/f');
say $fs->read('/to/d/f'); # OK
# copy dir recursively
$fs->remove_tree('/to') if $fs->exists('/to');
$fs->copy_dir('/from' => '/to');
say $fs->read('/to/d/f'); # OK
$fs->sysopen($fh, '/c', 'w+');
$fs->syswrite($fh, "123456");
$fs->sysseek($fh, 0);
$fs->sysread($fh, \my $buf, 3);
say $buf; # 123
# traversing
$fs->find_files(
# where to start (/ => /tmp/testfs)
'/',
# do something with file
sub ($path) {
say $path;
},
# skip dirs like .git
sub ($path) {
scalar fileparse($path) !~ /^\./;
}
);
$fs->find_files(
['/'],
sub ($path) {
say "FOUND: ", $path;
}
);
# FSROOT
use Evo::Fs 'FSROOT';
say join ', ', FSROOT->ls('/');
DESCRIPTION
An abstraction url-like layer between file system and your application. Every path is relative to root
.
You wan't be able to do something like this:
my $fs = Evo::Fs->new(root => '/tmp/fs');
my $path = '../fs2/foo';
$fs->write($path);
This is a security protection. But you can use "cd" instead
my $fs2 = $fs->cd('../fs2');
$fs2->write('foo' => 'OK');
EXPORTS
FSROOT
Return a single instance of Evo::Fs where root is /
ATTRIBUTES
root
my $fs = Evo::Fs->new(root => '/tmp/test-root');
METHODS
cd
Create a new Evo::FS
instance. Also this is the only way to traverse up
my $fs = Evo::Fs->new(root => '/tmp/fs');
my $fs2 = $fs->cd('../fs2');
my $fs_child = $fs->cd('child');
copy_file($self, $from, $to)
Copy file, die if already exists
copy_dir($self, $from, $to)
Copy directory recursively, if directory $to
exists, replace it content, create it otherwise. And for the children do the same
This functions kinda try to synchronize one path with another. Unlike cp -a
, 2 invocations of this functions will lead to the same result (cp
tries to check, if directory $to
exists and copies $from
to it in this case, this functions won't do this)
my $fs = Evo::Fs->new(root => File::Temp->newdir);
$fs->write('/base/child/file' => 'OK');
$fs->make_tree('/copy/child'); # just to show that directory can exist
$fs->copy_dir('/base', 'copy');
say $fs->read('/copy/child/file'); # OK
In this example, directory /copy/child
already exists, so a single file /base/child/file
will be silenty copied to /copy/child/file
sysopen ($self, $path, $mode, $perm=...)
my $fh = $fs->open('/foo/bar.txt', 'w');
Open a file and return a filehandle. Create parent directories if necessary. See "sysopen" for list of modes
append, write, read, read_ref
$fs->write('/tmp/my/file', 'foo');
$fs->append('/tmp/my/file', 'bar');
say $fs->read('/tmp/my/file'); # foobar
say $fs->read_ref('/tmp/my/file')->$*; # foobar
Read, write or append a content to the file. Dirs will be created if they don't exist. Use lock 'ex' for append and write and lock 'sh' for read during each invocation
write_many
Write many files using write
sysseek($self, $position, $whence='start')
Whence can be one of:
sysread ($self, $fh, $ref, $length[, $offset])
Call sysread
but accepts scalar reference for convinience
syswrite($self, $fh, $scalar, $length, $offset)
Call syswrite
sysopen ($self, $fh, $path, $mode, $perm=...)
$fs->sysopen(my $fh, '/tmp/foo', 'r');
Mode can be one of:
* w Open file for writing. The file is created (if it does not exist) or truncated (if it exists). * wx Like w
but fails if path exists. * w+ Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists). * wx+ Like w+
but fails if path exists.
* a Open file for appending. The file is created if it does not exist. * ax Like a
but fails if path exists. * a+ Open file for reading and appending. The file is created if it does not exist. * ax+ Like a+
but fails if path exists.
rename($self, $oldpath, $newpath)
Rename a file.
stat($self, $path)
Return a Evo::Fs::Stat object
path2real($virtual)
Convert a virtual path to the real one.
find_files($self, $dirs, $fn, $pick=undef)
$fs->find_files('./tmp', sub ($fh) {...}, sub ($dir) {...});
$fs->find_files(['/tmp'], sub ($fh) {...});
Find files in given directories. You can skip some directories by providing $pick->($dir)
function. This will work ok on circular links, hard links and so on. Every path will be passed to $fn->($fh)
only once even if it has many links.
So, in situations, when a file have several hard and symbolic links, only one of them will be passed to $fn
, and potentially each time it can be different path for each find_files
invocation.
See "traverse" for examining all nodes. This method just decorate it's arguments
SKIP_HIDDEN
You can also traverse all files, but ignore hidden directories, like ".git" this way:
use Evo '-Fs FS SKIP_HIDDEN';
FS->find_files('./', sub($path) { say $path; }, SKIP_HIDDEN)
traverse($self, $dirs, $fn, $pick=undef)
Traverse directories and invoke $fn->$path
for each child node.
Each file is processed only once no matter how many links it has. So instead of a real filename you may be getting a link and never a real name depending on which one (file or link) was met first
You can provide $pick->($dir)
to skip directories, for example, to skip hidden ones. By default all directories are processed
$fs->traverse('/tmp', sub ($path) {...}, sub ($dir) {...});
$fs->traverse(['/tmp'], sub ($path) {...},);
Also this method doesn't try to access directories without X and R permissions or pass them to $pick
(but such directories will be passed to fn
because are regular nodes)
In most cases you may want to use "find_files" instead.
AUTHOR
alexbyk.com
COPYRIGHT AND LICENSE
This software is copyright (c) 2016 by alexbyk.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.