perl.gg / snippets

Io All Recursion

2024-07-11

IO::All is one of those modules that makes you wonder why file operations were ever complicated. Today we're looking at recursive file searching - and the key insight is surprisingly subtle.

Part 1: THE CAPITAL LETTER THAT CHANGES EVERYTHING

Here's the most important thing to remember:
All_Files # Recursive - goes into subdirectories all_files # Non-recursive - current directory only
That capital 'A' makes all the difference! It's easy to miss, and you'll spend an hour wondering why your recursive search only finds files in the top directory. Ask me how I know.

Part 2: THE VERBOSE APPROACH

Let's start with the explicit, readable version:
use IO::All; my $dir = '/path/to/search'; my @files = io($dir)->All_Files; foreach my $file (@files) { print $file->name, "\n"; }
The io() function creates an IO::All object from a path. Then All_Files (capital A!) returns a list of all files in that directory AND all its subdirectories, recursively, forever, until it hits the bottom.

Each item in @files is itself an IO::All object, so you can call methods on it like ->name, ->size, ->mtime, and more.

Part 3: THE CONCISE ONE-LINER

Now let's get Perlish about it. Say you want to find all index.html files in a directory tree:
use IO::All; my @indexes = grep { $_->filename eq 'index.html' } io($dir)->All_Files;
That's it. One line. We're using grep to filter the recursive file list, and ->filename gives us just the file's name without the path.

Want to do something with them immediately?

print $_->name, "\n" for grep { $_->filename eq 'index.html' } io($dir)->All_Files;

Part 4: USEFUL METHODS ON FILE OBJECTS

Each file object you get back is powerful. Here are some handy methods:
$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
So finding all Perl files over 1KB becomes:
my @big_perl = grep { $_->ext eq 'pl' && $_->size > 1024 } io($dir)->All_Files;

Part 5: WORKING WITH DIRECTORIES TOO

Need directories as well as files? There's All (capital A again):
my @everything = io($dir)->All; # Files AND directories my @dirs_only = io($dir)->All_Dirs; # Just directories
The lowercase versions (all, all_files, all_dirs) do the same thing but without recursion - just the immediate contents.

Part 6: A PRACTICAL EXAMPLE

Here's a real-world script that finds all Perl files and counts their lines:
#!/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;
This finds all .pl and .pm files, counts their lines, and gives you a summary. The regex /^p[lm]$/ matches 'pl' or 'pm' - covering both scripts and modules.

Part 7: REMEMBER THE CAPITAL A

I'll say it one more time because it's that important:
All_Files # RECURSIVE - this is probably what you want all_files # not recursive - just current directory
Tattoo it on your brain. Frame it on your wall. The capital A is your friend for deep directory diving.

IO::All turns what would be 20 lines of opendir/readdir/recursion into elegant one-liners. Once you start using it, you'll wonder how you ever lived without it.

Happy file hunting!

Created By: Wildcard Wizard. Copyright 2026