Search code examples
perlreaddir

Perl's 'readdir' Function Result Order?


I am running Perl in Windows and I am getting a list of all the files in a directory using readdir and storing the result in an array. The first two elements in the array seem to always be "." and "..". Is this order guaranteed (assuming the operating system does not change)?

I would like to do the following to remove these values:

my $directory = 'C:\\foo\\bar';

opendir my $directory_handle, $directory 
    or die "Could not open '$directory' for reading: $!\n";

my @files = readdir $directory_handle;
splice ( @files, 0, 2 ); # Remove the "." and ".." elements from the array

But I am worried that it might not be safe to do so. All the solutions I have seen use regular expressions or if statements for each element in the array and I would rather not use either of those approaches if I don't have to. Thoughts?


Solution

  • There is no guarantee on the order of readdir. The docs state it...

    Returns the next directory entry for a directory opened by opendir.

    The whole thing is stepping through entries in the directory in whatever order they're provided by the filesystem. There is no guarantee what this order may be.

    The usual way to work around this is with a regex or string equality.

    my @dirs = grep { !/^\.{1,2}\z/ } readdir $dh;
    
    my @dirs = grep { $_ ne '.' && $_ ne '..' } readdir $dh;
    

    Because this is such a common issue, I'd recommend using Path::Tiny->children instead of rolling your own. They'll have figured out the fastest and safest way to do it, which is to use grep to filter out . and ... Path::Tiny fixes a lot of things about Perl file and directory handling.