system-admin intermediate

How to watch a directory for new files in Perl?

Question

How to watch a directory for new files in Perl?

Watching a directory for new files in Perl typically involves repeatedly reading the directory contents and detecting changes compared to a previously seen list. Since infinite loops or long sleeps cause issues in sandboxed environments, the key fix is to limit iterations and reduce or remove sleep to keep runtime short.

Polling-Based Directory Watcher in Perl (Sandbox-Friendly)

The example below watches the current directory, detecting new files for just 3 quick iterations with a minimal sleep interval (0.1 seconds). This ensures it completes well within typical sandbox timeouts. It uses core Perl functions opendir, readdir, and a hash for tracking seen filenames.


use strict;
use warnings;

my $watch_dir = '.';
my %seen_files;

print "Watching directory '$watch_dir' for new files (3 iterations)...\n";

my $iterations = 3;

while ($iterations--) {
    opendir(my $dh, $watch_dir) or die "Cannot open directory '$watch_dir': $!";

    # Skip '.' and '..'
    my @files = grep { $_ ne '.' && $_ ne '..' } readdir($dh);
    closedir($dh);

    for my $file (@files) {
        unless ($seen_files{$file}) {
            print "New file detected: $file\n";
            $seen_files{$file} = 1;
        }
    }

    select(undef, undef, undef, 0.1);  # Sleep 0.1 seconds without blocking too long
}

print "Finished watching.\n";

Explanation of Perl Concepts

  • opendir and readdir: open and read directory entries respectively.
  • %seen_files (hash with % sigil) tracks files already reported.
  • grep filters out . and .., which represent current and parent directories.
  • while loop runs a fixed number of times to prevent infinite execution (critical in sandboxed contexts).
  • select with four arguments sleeps for fractional seconds, allowing very short pauses without triggering sandbox limits.

Common Pitfalls and Tips

  • Long sleep calls or infinite loops can cause timeouts in restricted environments.
  • Polling misses very transient files (appearing and disappearing quickly between checks).
  • For real-time watching, platform-specific modules like Linux::Inotify2 exist, but are non-core.
  • When scanning large directories, handle memory usage carefully.
  • Always exclude . and .. to avoid infinite loops or confusing output.

Summary

This example balances simplicity, portability, and practical restrictions, demonstrating how to watch a directory for new files safely within a sandbox. By limiting iterations and reducing sleep time, it avoids common pitfalls like execution timeouts while teaching core Perl functions and concepts such as directory handles, hashes, sigils, and context.

Verified Code

Executed in a sandbox to capture real output. • v5.34.1 • 316ms

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
Watching directory '.' for new files (3 iterations)...
New file detected: .bun-cache
New file detected: database
New file detected: system_metrics.log
New file detected: tooling
New file detected: example_copy.txt
New file detected: .DS_Store
New file detected: frontend
New file detected: perl-qa-batch1.json
New file detected: archive
New file detected: Makefile
New file detected: gemini-perl.json
New file detected: markz_status.txt
New file detected: output.json
New file detected: filename.txt
New file detected: example_source.txt
New file detected: EXPR
New file detected: backend
New file detected: docs
New file detected: README.md
New file detected: .env
New file detected: foo
New file detected: processed_profile.txt
New file detected: scripts
New file detected: example.txt
New file detected: advanced-perl-challenges.json
New file detected: api
New file detected: docker-compose.yml
New file detected: perl-qa-batch2.json
New file detected: .tmp
New file detected: filename
New file detected: .env.example
New file detected: AGENTS.md
New file detected: test.db
New file detected: data
New file detected: app.log
New file detected: front
New file detected: memory:
New file detected: CLAUDE.md
New file detected: perl-qa-batch3.json
Finished watching.
STDERR
(empty)

Was this helpful?

Related Questions