Opening a directory in Perl

opendir DIRHANDLE ,  EXPR

Opens a directory named EXPR for processing by readdir(), telldir(), seekdir(), rewinddir(), and closedir(). Returns TRUE if successful and, of course, false, if you don't have permission to read the directory, or it doesn't exist, or the hard drive has crashed, or if the computer is just cranky.

DIRHANDLE may be an expression whose value can be used as an indirect dirhandle, usually the real dirhandle name. If DIRHANDLE is an undefined scalar variable (or array or hash element), the variable is assigned a reference to a new anonymous dirhandle. DIRHANDLEs have their own namespace separate from FILEHANDLEs. it should be all uppercase, like a filehandle, if you want to please other Perl programmers and keep Perl from confusing READDIR (a less than ideal, but valid name for a directory handle) with readdir (another Perl function).

EXPR is an express that references a path and directory. You can use forward slashes (/) on Windows and DOS and your Perl script will then work in both the *nix and M$ worlds.

Here is a simple example that opens a directory in the path you pass to it and reads all the file names into a hash.

$path = shift;
opendir(DIR, $path) or die “Cannot open $path: $!”;
@FILES=readdir(DIR);
closedir(DIR);

Note that the names in FILES do not include the path and do include "." and ".." which you probably don't care to have. You can eliminate them with;

@FILES=grep(!/^\.\.?}$/, readdir(DIR));

The regular expression used in the grep can be extended to filter all sorts of ways, returning only files with a specific extension or starting with some text, etc...

To check for all the subdirectories in a directory, try code like this:


    $path = shift;
    $path = "." unless $path;
    
    opendir( DIR, $path )
        or die "Can't open $path: $!";
    
    while ( $entry = readdir( DIR ) ) {
        $type = ( -d "$path\\$entry" ) ? "dir" : "file"; # $path is crucial!
        print "$type\t$entry\n";
    }
    
    closedir( DIR );

It's a common mistake to leave out the $path from the -d check. If you do this, perl thinks you're talking about files in the current directory. Since the dirs don't -e in your current directory, they definitely don't -d. Exceptions are . and .., which exist in every directory.

opendir, redir, closedir offer the most power and flexibility; but if you just want to read the files out of directory, you can also glob them:

$path = shift;
$path .= "/*"
while( $name=glob($path) ) { print "$name"; }

The * added to the path is a c shell (no matter what shell you use) glob pattern and NOT a regular expression. "?" matches any single character, "*" matches any number of characters, "[abc]" matches the characters "a", "b", or "c" (but not on a Mac) and "{abc,b,c}" matches the strings "abc", "b", or "c". glob DOES return the path along with the file name. Why don't you see glob often in Perl code? Because you can short-hand it like this:

while( </tmp/*.txt> ) print

so it is being used more than you think. When you just want all the include files in the folder, nothing beats <*.h> !

See:

See also:

Questions: