Filehandles, files, directories

glob#

Expand a shell-style filename pattern into the list of matching paths.

glob takes a pattern string such as "*.c" or "src/**/*.pm" and returns the filenames on disk that match, in the same style a Unix shell would produce. In list context it returns every match at once; in scalar context it acts as a stateful iterator, returning one match per call and undef when the list is exhausted. With no argument, glob expands the pattern in $_.

Synopsis#

glob EXPR
glob
<PATTERN>

What you get back#

In list context, a (possibly empty) list of filenames. An empty list means the pattern did not match — it is not an error and does not set $!.

In scalar context, glob is an iterator: each call returns the next match, and after the last match one more call returns undef. The iterator state is per-call-site, so two while (my $f = glob ...) loops at different source locations do not interfere.

my @mp3  = glob "*.mp3";            # list context
while (my $f = glob "*.mp3") { }    # scalar context, iterator

Global state it touches#

  • $_ — read when glob is called with no argument.

  • glob itself does not set $! on “no matches”. A non-match is a legitimate empty list, not a failure.

  • When a glob expression is used as the condition of a while or for loop, Perl implicitly assigns the result to $_ and tests for definedness, not truth — so a filename of "0" still keeps the loop running.

The <...> shortcut and how Perl picks it#

<*.c> is an alternative syntax for glob("*.c"). The angle-bracket form shares a reader with <FH> (readline); the parser decides which one you meant at compile time based on what sits between the angle brackets:

  • Bareword that could be a filehandle (<STDIN>, <FH>) → readline.

  • A simple scalar (<$fh>) → readline on that handle.

  • Anything that looks like a pattern (<*.c>, <"*.txt">, <${dir}/*>) → glob.

The named function glob is unambiguous and more searchable. Prefer it in new code; reach for <...> only for the shortest throwaway patterns.

my @txt = <"*.txt">;                # same as glob '"*.txt"'
my @txt = glob "*.txt";             # recommended

Whitespace splits the pattern#

glob splits its argument on whitespace and treats each segment as a separate pattern. The results are concatenated:

my @sources = glob "*.c *.h";       # all .c OR .h files
my @all     = glob ".* *";          # every entry in cwd

To glob a filename that itself contains spaces, wrap it in an inner pair of quotes so the split sees one segment:

my @spacey = glob '"*e f*"';        # files with "e f" in the name
my @spacey = glob q("*e f*");       # same, q() for clarity
my @spacey = <"*e f*">;             # same via the shortcut form

Interpolating a variable into a spacey pattern:

my @spacey = glob "'*${var}e f*'";
my @spacey = glob qq("*${var}e f*");

If the whitespace-splitting rule gets in the way, use File::Glob’s bsd_glob directly — it takes the pattern verbatim.

Brace expansion without a wildcard#

If the only special characters are non-empty braces, glob does not touch the filesystem at all: it just enumerates the Cartesian product of the alternatives. This is useful for generating string combinations:

my @pairs = glob "{apple,tomato,cherry}={green,yellow,red}";
# apple=green, apple=yellow, apple=red,
# tomato=green, tomato=yellow, tomato=red,
# cherry=green, cherry=yellow, cherry=red

File::Glob — the engine, and its options#

glob is implemented on top of File::Glob’s bsd_glob. Importing the module’s tags tunes behaviour for the whole compilation unit:

  • :nocase — case-insensitive matching.

  • :case — force case-sensitive matching (the default on most Unix filesystems).

  • :globally — replace the core glob operator with bsd_glob so every glob(...) and <...> in the file picks up your options.

use File::Glob qw(:globally :nocase);
my @txt = glob "readme*";           # README, readme.txt, Readme.md

Call bsd_glob directly when you need flags per call, or when you want to bypass the whitespace-splitting rule:

use File::Glob qw(bsd_glob GLOB_TILDE GLOB_BRACE);
my @files = bsd_glob("~/docs/*.{md,rst}", GLOB_TILDE | GLOB_BRACE);

Examples#

List every Perl source file in the current directory:

my @perl_files = glob "*.pl *.pm";

Iterate MP3 files one at a time — useful when the list might be large and you do not want to materialise it:

while (my $song = glob "*.mp3") {
    process($song);                 # one filename per iteration
}

Recursive patterns are not built in; * does not cross /. Walk the tree with File::Find or combine glob with an explicit traversal:

my @all_c;
for my $dir (glob "src/*") {
    push @all_c, glob "$dir/*.c" if -d $dir;
}

Use the iterator form in a while condition — the result is assigned to $_ and tested for definedness, so filenames like "0" do not terminate the loop:

while (<*.log>) {
    unlink $_ if -M $_ > 30;        # older than 30 days
}

Case-insensitive match for a whole file:

use File::Glob qw(:globally :nocase);
my @readmes = glob "readme*";

Edge cases#

  • No matches: returns the empty list. No warning, no $! set. If you need “pattern had to match”, check scalar @files yourself.

  • glob with no argument: uses $_. Bare glob inside while (<>) is rarely what you want — the pattern will be whatever line of input you just read.

  • while (glob ...) assigns to $_ and tests definedness: a filename "0" is false under normal boolean rules, but the loop still runs because the condition is defined $_. This matches the rule for readline in the same position.

  • Wildcards and whitespace: the split-on-whitespace rule means glob "a b" searches for a and b as two patterns, not for the literal string "a b". Use inner quotes or bsd_glob when the filename legitimately contains spaces.

  • Hidden files: a leading . is not matched by * — you need an explicit .* segment (glob ".* *") to include dotfiles. This matches shell glob semantics, not regex semantics.

  • Tilde expansion: glob "~/foo" works because File::Glob expands ~ by default. Writing it through bsd_glob without GLOB_TILDE in the flags, you get a literal ~.

  • Interpolation inside <...>: <$var/*.c> interpolates $var at runtime. Using the angle-bracket form does not escape you from Perl’s normal double-quote rules.

  • Angle-bracket ambiguity: <FOO> is a handle read, <$foo> is a handle read, <*.c> is a glob. <$foo/*.c> — one scalar plus pattern characters — is a glob. The resolution is compile-time; runtime changes to $foo do not re-decide it.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • opendir — open a directory handle for finer-grained traversal than pattern matching gives you

  • readdir — read entries from a directory handle one at a time; pair with opendir when you need every entry (including ones glob hides, like dotfiles) or file-type info

  • readline — the other meaning of <...>; shares the angle-bracket syntax but reads lines from a filehandle

  • File::Glob — the underlying implementation; use bsd_glob directly for per-call flags and to bypass the whitespace-splitting rule

  • $_ — default pattern source for bare glob, and the variable implicitly assigned when glob is used as a while/for loop condition