Badger...Visitor(3pm)
π Badger::Filesystem::Visitor β the visitor that walks your filesystem like it owns the place π
okay so this is the Badger::Filesystem::Visitor(3pm) page from the User Contributed Perl Documentation, and bestie, we're about to go on a journey. Literally. Through a filesystem. Let's get into it π¦
β¨ NAME β¨
Badger::Filesystem::Visitor β it's a visitor for traversing filesystems, no cap π
β¨ SYNOPSIS β¨
use Badger::Filesystem 'FS';
my $controls = {
files => '*.pm', # collect all *.pm files
dirs => 0, # ignore dirs
in_dirs => 1, # but do look in dirs for more files
not_in_dirs => ['.svn', '.git'], # don't look in these dirs
};
my @files = FS
->dir('/path/to/dir')
->visit($controls)
->collect;
look at that. clean. iconic. it's giving "I traverse directories and I slay" π
β¨ DESCRIPTION β¨
so the Badger::Filesystem::Visitor module implements a base class visitor object that you can use to traverse filesystems. that's the whole vibe π
the most common use of a visitor is to walk a filesystem and find files and directories that match (or don't match) some particular set of criteria β like file name, type, size, whatever. and Badger::Filesystem::Visitor hands you a whole bunch of configuration options to make those common tasks easy. for anything more complicated, you can subclass the module and build your own custom visitor. main character energy, fr fr π
the easiest way to create and use a visitor is to call the visit() method on any of the Badger::Filesystem objects. in most cases you'll want to call it against a Badger::Filesystem::Directory object β but like, nothing is stopping you from calling it against a Badger::Filesystem::File object (though your visitor won't have anywhere to visitor beyond that single file, so it doesn't really serve any practical purpose, bestie π). and if you call it against a top-level Badger::Filesystem object, then it gets applied to the root directory of the filesystem. wild, but okay π
use Badger::Filesystem 'Dir';
my $dir = Dir('/path/to/search/dir');
my $visitor = $dir->visit( files => 1, dirs => 0 );
my $collect = $visitor->collect;
so here's the tea on what's actually happening β β the visit() method first creates a "Badger::Filesystem::Visitor" object by delegating to the Badger::Filesystem visitor() method. this configures the new visitor using any parameters you passed as arguments, specified either as a list or a reference to a hash array of named parameters. if you pass no parameters at all, the defaults get used. then the visitor's visit() method is called, passing the Badger::Filesystem::Directory object as an argument. and so begins the visitor's journey into the filesystemβ¦ π§β¨
the configuration parameters are what define what the visitor should collect on its travels. here are some examples:
$dir->visit(
files => 1, # collect all files
dirs => 0, # ignore all dirs
);
$dir->visit(
files => '*.pm', # collect all .pm files
dirs => 0, # ignore all dirs
);
$dir->visit(
files => '*.pm', # as above, no dirs are collected
dirs => 0, # but we do enter into them to
in_dirs => 1, # find more files
);
$dir->visit(
files => '*.pm', # collect *.pm files
dirs => 0, # don't collect dirs
in_dirs => 1, # do recurse into them
not_in_dirs => '.svn', # but don't look in .svn dirs
);
$dir->visit(
files => 'foo' # find all files named 'foo'
dirs => qr/ba[rz]/, # and all dirs named 'bar' or 'baz'
in_dirs => 1, # recurse into subdirs
);
you can also define subroutines to filter the files and/or directories you're interested in π«Ά the first argument passed to the subroutine is the Badger::Filesystem::File or Badger::Filesystem::Directory object being visited. the second argument is a reference to the visitor object.
in this next example we collect files smaller than 420 bytes, and directories that contain a metadata.yaml file. very specific. very demure β¨
$dir->visit(
files => sub { shift->size < 420 },
dirs => sub { shift->file('metadata.yaml')->exists }
in_dirs => 1,
);
you can also specify a reference to a list of items, where each item can be a simple flag (0/1), a name to match, a regular expression, or a subroutine reference. each one gets tested in turn until the first one matches. and if none of them match? the file or directory gets ignored. bye π
$dir->visit(
files => ['foo', qr/wiz/i, \&my_file_sub ],
dirs => [ qr/ba[rz]/, \&my_dir_sub ],
in_dirs => 1,
);
and on top of all the inclusive matches shown above, you can also tell the visitor what to exclude π you can use any of the same pattern specifications as the inclusive options β 0/1 flags, names, regexen, subroutines, or list refs containing any of the above.
$dir->visit(
no_files => '*.bak',
no_dirs => ['tmp', qr/backup/i],
not_in_dirs => ['.svn', '.DS_Store'],
);
once the visit is done, the collect() method can be called to return a list (in list context) or a reference to a list (in scalar context) of the items that got collected π that list will contain Badger::Filesystem::File and Badger::Filesystem::Directory objects.
my $collect = $visitor->collect; # list ref in scalar context
my @collect = $visitor->collect; # list in list context
β¨ CONFIGURATION OPTIONS β¨
NOTE: I'm planning the add the 'accept', 'ignore', 'enter', and 'leave' aliases for 'files', 'no_files', 'in_dirs' and 'not_in_dirs'. Can't think of better names for 'dirs' and 'no_dirs' though... (lowkey relatable, naming things is the worst π)
πΈ files / accept (todo)
a pattern specifier indicating the files that you want to match.
πΈ no_files / ignore (todo)
a pattern specifier indicating the files that you don't want to match.
πΈ dirs / directories
a pattern specifier indicating the directories that you want to match.
πΈ no_dirs / no_directories
a pattern specifier indicating the directories that you don't want to match.
πΈ in_dirs / in_directories / enter (todo)
a pattern specifier indicating the directories that you want to enter to search for further files and directories. go in, bestie, the vibes are immaculate πͺβ¨
πΈ not_in_dirs / not_in_directories / leave (todo)
a pattern specifier indicating the directories that you don't want to enter to search for further files and directories. do not pass go. do not collect $200 π
πΈ at_file
a reference to a subroutine that you want called whenever a file of interest is visited β meaning one that's included by files and not excluded by no_files. the subroutine gets passed a reference to the visitor object, and a reference to a Badger::Filesystem::File object representing the file.
$dir->visit(
at_file => sub {
my ($visitor, $file) = @_;
print "visiting file: ", $file->name, "\n";
}
);
πΈ at_dir / at_directory
a reference to a subroutine that you want called whenever a directory of interest is visited β meaning one that's included by dirs and not excluded by no_dirs. the subroutine gets passed a reference to the visitor object, and a reference to a Badger::Filesystem::Directory object representing the directory.
$dir->visit(
at_dir => sub {
my ($visitor, $dir) = @_;
print "visiting dir: ", $dir->name, "\n";
}
);
if the function returns a true value, then the visitor keeps on visiting any files or directories within it according to its usual rules β so if the directory is listed in a not_in_dirs rule, it still won't be entered, periodt. but if the function returns a false value, then the directory gets skipped entirely. π«
β¨ METHODS β¨
πΈ new(%params)
constructor method to create a new "Badger::Filesystem::Visitor". baby's first visitor πΌ
β¨ TRAVERSAL METHODS β¨
πΈ visit($node)
general purpose dispatch method to visit any node. this method calls the accept() method on the $node, passing the visitor $self reference as an argument. the $node will then call back to the correct method for the node type (e.g. visit_file() or visit_dir()). it's giving β¨delegationβ¨
πΈ visit_path($path)
this method is called to visit base class Badger::Filesystem::Path objects. it doesn't do anything useful at present, but probably should. (we love an honest king π)
πΈ visit_file($file)
this method is called to visit a Badger::Filesystem::File object.
πΈ visit_directory($dir) / visit_dir($dir)
this method is called to visit a Badger::Filesystem::Directory object.
πΈ visit_directory_children($dir) / visit_dir_kids($dir)
this method is called to visit the children of a Badger::Filesystem::Directory object. the kids!! π§β¨
β¨ SELECTION METHODS β¨
πΈ accept_file($file)
this method applies any selection rules defined for the visitor to determine if a file should be collected or not. it returns a true value if it should, or a false value if not.
πΈ accept_directory($dir) / accept_dir($dir)
this method applies any selection rules defined for the visitor to determine if a directory should be collected or not. it returns a true value if it should, or a false value if not.
πΈ enter_directory($dir) / enter_dir($dir)
this method applies any selection rules defined for the visitor to determine if a directory should be entered or not. it returns a true value if it should, or a false value if not.
πΈ filter($type,$method,$item)
this is a general purpose method which implements the selection algorithm for the above methods. for example, the accept_file() method is implemented as:
return $self->filter( files => name => $file )
&& ! $self->filter( no_files => name => $file );
the first argument provides the name of the configuration parameter which defines the filter specification. the second argument is the name of the file/directory method that returns the value that should be compared (in this case, the file or directory name). the third argument is the file or directory object itself. π
β¨ COLLECTION METHODS β¨
Okay bestie, this is where the visitor actually keeps stuff π Like, it looks at files and dirs, and these are the lil methods that decide what goes in the goodie bag.
collect_file($file)
So when the visitor's accept_file() method says "yep, taking this one," this method gets the call. Here's the tea:
- If an
at_filehandler is defined, it gets called, and it gets handed a reference to the visitor plus the file being visited. If that handler returns a true value, then we move on and callcollect(). If it doesn't return true, we bounce immediately, no collect, no nothing. π« - If there's no
at_filehandler defined at all? Then this method just delegates straight tocollect(). Easy.
collect_directory($dir) / collect_dir($dir)
Same energy, but for directories πΈ When the visitor's accept_directory() method accepts a directory, this one gets called. And listen:
- If an
at_directoryhandler is defined, it's called with a reference to the visitor and the directory being visited as arguments. True value back? Then we go on to callcollect(). Not true? It returns right away and it short-circuits any further visits to files or directories hanging out inside it. Like, door closed, nobody's home. πͺ - No
at_directoryhandler defined? It delegates tocollect(), same as above.
collect(@items)
The main character of collection π«Ά This is what the visitor uses to actually collect items of interest. Whatever arguments you pass get added to the internal collect list.
$visitor->collect($this, $that);
And when you want them back? In list context you get the list, in scalar context you get a reference to a list. Choose your fighter:
my $collect = $visitor->collect;
my @collect = $visitor->collect;
identify(%items)
Basically collect()'s cousin, except this one is for building a lookup table so you can identify files and directories by name. Ngl though β it's currently not used for anything at all. It's just sitting there looking cute, and it may be one day RSN. π
π AUTHOR
Andy Wardley <http://wardley.org/>
π COPYRIGHT
Copyright (C) 2005-2009 Andy Wardley. All rights reserved.
π SEE ALSO
Badger::Filesystem
And that's a wrap, bestie! π¦ This was Badger...Visitor(3pm) from the User Contributed Perl Documentation, built from perl v5.36.0 and dated 2023-08-28. Slay, go forth, and collect responsibly. π
β¨
π¦ where this page comes from
- debian trixie: libbadger-perl 0.16-3 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: libbadger-perl 0.16-3 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libbadger-perl 0.16-3 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms