Io All Recursion
This page shows how to use the IO::All module to search through directories and subdirectories recursively. The trick lies in a single capital letter that changes how the search behaves.Part 1: THE CAPITAL LETTER THAT CHANGES EVERYTHING
The difference between recursive and non-recursive search comes down to capitalization.You will likely miss this detail at first, and you will spend time debugging a search that only checks the top folder. The capital letter controls whether the module walks into subdirectories.All_Files # Recursive - goes into subdirectories all_files # Non-recursive - current directory only
Part 2: THE VERBOSE APPROACH
We can start with the straightforward version that is easy to read and modify later.Theuse IO::All; my $dir = '/path/to/search'; my @files = io($dir)->All_Files; foreach my $file (@files) { print $file->name, "\n"; }
io() function wraps a directory path into an IO::All object. The All_Files method then walks every subdirectory and returns a flat list of the files it finds.
Every entry in that list is an IO::All object, which means you can call methods like ->name, ->size, or ->mtime directly on it.
Part 3: THE CONCISE ONE-LINER
You can compress that same logic into a single line when you need a quick filter.That is enough code to run the search. We useuse IO::All; my @indexes = grep { $_->filename eq 'index.html' } io($dir)->All_Files;
grep to filter the recursive file list, and ->filename returns just the file name without the surrounding path.
You can also run an action on each match right inside the filter.
print $_->name, "\n" for grep { $_->filename eq 'index.html' } io($dir)->All_Files;
Part 4: USEFUL METHODS ON FILE OBJECTS
Every file object you get back carries a set of built-in methods for inspection.You can combine those methods to filter by type and size in one statement.$file->name # Full path: /path/to/file.txt $file->filename # Just the name: file.txt $file->size # Size in bytes $file->mtime # Modification time (epoch) $file->ext # Extension: txt $file->slurp # Read entire contents $file->dir # Parent directory as IO::All object
my @big_perl = grep { $_->ext eq 'pl' && $_->size > 1024 } io($dir)->All_Files;
Part 5: WORKING WITH DIRECTORIES TOO
You can ask the same methods to return directories alongside files.The lowercase versions (my @everything = io($dir)->All; # Files AND directories my @dirs_only = io($dir)->All_Dirs; # Just directories
all, all_files, all_dirs) do the same thing but without recursion, meaning they only list the immediate contents of the starting folder.
Part 6: A PRACTICAL EXAMPLE
Here is a complete script that finds every Perl file in a tree and tallies their line counts.This script finds all#!/usr/bin/perl use strict; use warnings; use IO::All; my $dir = shift || '.'; my $total_lines = 0; for my $file (grep { $_->ext =~ /^p[lm]$/ } io($dir)->All_Files) { my @lines = $file->slurp; my $count = scalar @lines; $total_lines += $count; printf "%6d %s\n", $count, $file->name; } print "-" x 40, "\n"; printf "%6d TOTAL\n", $total_lines;
.pl and .pm files, counts their lines, and prints a summary. The regex /^p[lm]$/ matches either pl or pm, which covers both standalone scripts and Perl modules.
Part 7: REMEMBER THE CAPITAL A
I will repeat the rule one more time because it controls whether your search actually goes deep.The capital letter is what turns a shallow scan into a full directory dive.All_Files # RECURSIVE - this is probably what you want all_files # not recursive - just current directory
IO::All turns what would otherwise be twenty lines of opendir, readdir, and manual recursion into compact one-liners. You will likely find yourself reaching for it whenever a directory tree needs inspection.
Happy file hunting!
perl.gg