Skip to content

Perl Directories

Perl provides built-in functions for interacting with the file system’s directory structure. These allow you to list directory contents, create, remove, and change directories.

Core Directory Functions:

opendir(my $dh, $dirname) or die "Cannot open directory '$dirname': $!"; # Open a directory
my @entries = readdir($dh); # Read entries from the directory
rewinddir($dh); # Reset pointer to the beginning of the directory stream
telldir($dh); # Get current position in the directory stream
seekdir($dh, $pos); # Set position in the directory stream
closedir($dh); # Close the directory handle
mkdir($new_dir, $permissions) or die "Cannot create directory '$new_dir': $!"; # Create a directory
rmdir($dir_to_remove) or die "Cannot remove directory '$dir_to_remove': $!"; # Remove an empty directory
chdir($target_dir) or die "Cannot change to directory '$target_dir': $!"; # Change current directory

Always use use strict; and use warnings; in your scripts. Use lexical directory handles (my $dh) for better code safety.

This is the traditional way to list directory contents.

#!/usr/bin/perl
use strict;
use warnings;
my $dir_path = '.'; # Current directory
opendir(my $dh, $dir_path) or die "Can't open $dir_path: $!";
print "Entries in '$dir_path':\n";
while (my $entry = readdir($dh)) {
# readdir also returns '.' and '..'
next if $entry eq '.' or $entry eq '..';
print "$entry\n";
}
closedir($dh);

The glob() function (or <*>) expands filename patterns, similar to shell globbing.

#!/usr/bin/perl
use strict;
use warnings;
my $dir_pattern = './*'; # All files and directories in current directory
print "Entries matching '$dir_pattern' (via glob):\n";
my @files = glob($dir_pattern);
# Alternatively: my @files = <$dir_pattern>;
foreach my $file (@files) {
print "$file\n";
}
# To get only .txt files in /tmp:
# my @text_files = glob('/tmp/*.txt');
# To get hidden files (starting with .) in /tmp:
# my @hidden_files = glob('/tmp/.*');

glob() is convenient for simple patterns but may have security implications if the pattern comes from untrusted input.

You can combine readdir with grep to filter entries.

#!/usr/bin/perl
use strict;
use warnings;
my $dir_path = '.';
opendir(my $dh, $dir_path) or die "Can't open $dir_path: $!";
print "Perl files (.pl, .pm) in '$dir_path':\n";
my @perl_files = grep { /\.(pl|pm)$/i && -f "$dir_path/$_" } readdir($dh);
# The -f check ensures it's a file, not a directory ending in .pl
closedir($dh);
foreach my $file (@perl_files) {
print "$file\n";
}

The mkdir() function creates a new directory. The optional second argument specifies permissions (e.g., 0755).

#!/usr/bin/perl
use strict;
use warnings;
my $new_dir = './my_new_directory';
my $permissions = 0755; # Typical permissions
if (mkdir($new_dir, $permissions)) {
print "Directory '$new_dir' created successfully.\n";
# Clean up for example purposes
rmdir($new_dir) or warn "Could not remove test directory '$new_dir': $!";
} else {
warn "Couldn't create directory '$new_dir': $!";
}

The rmdir() function removes an empty directory.

#!/usr/bin/perl
use strict;
use warnings;
my $dir_to_remove = './empty_dir_to_remove';
# Create it first for the example
mkdir($dir_to_remove, 0755) or die "Setup: Could not create $dir_to_remove: $!";
if (rmdir($dir_to_remove)) {
print "Directory '$dir_to_remove' removed successfully.\n";
} else {
warn "Couldn't remove directory '$dir_to_remove': $!";
warn "(Is it empty? Do you have permissions?)";
}

To remove a directory with contents, you’d need to recursively delete its contents first. Modules like File::Path provide functions like remove_tree for this.

The chdir() function changes the script’s current working directory.

#!/usr/bin/perl
use strict;
use warnings;
use Cwd qw(getcwd);
my $target_dir = '/tmp'; # Example target directory
my $original_dir = getcwd(); # Get current working directory
print "Original directory: $original_dir\n";
if (chdir($target_dir)) {
my $new_current_dir = getcwd();
print "Successfully changed to '$target_dir'. New current directory: $new_current_dir\n";
# Change back to original directory (good practice if needed)
chdir($original_dir) or warn "Could not change back to $original_dir: $!";
} else {
warn "Couldn't change to directory '$target_dir': $!";
}

While Perl’s built-in functions are powerful, for more complex or object-oriented file and directory manipulation, consider using CPAN modules such as:

  • Path::Tiny: A small, fast, and convenient module for path operations.
  • Path::Class: Provides an object-oriented interface to files and directories.
  • File::Spec: For platform-independent path manipulation (e.g., joining path components).

These modules can often make code cleaner and more robust, especially for cross-platform applications.