tags:

views:

130

answers:

3
  opendir MYDIR, "$dir";
  my @FILES = readdir MYDIR;
  closedir MYDIR;

It appears that 99.9 % of the time the first two entries in the array are always “.” and “..”. Later logic in the script has issues if it is not true. I ran into a case where the directory entries appeared later. Is this indicative of the file system being corrupt or something else? Is there a known order to what opendir returns?

+13  A: 

It's always the operating-system order, presented unsorted raw.

While . and .. are very often the first two entries, that's because they were the first two entries created. If for some reason, one of them were deleted (via unnatural sequences, since it's normally prevented), the next fsck (or equivalent) would fix the directory to have both again. This would place one of the names at a later place in the list.

Hence, do not just "skip the first two entries". Instead, match them explicitly to reject them.

Randal Schwartz
How exactly would they get deleted? Can you describe one of those unnatural sequences?
ojblass
I think he means that something has to go wrong, since it's normally prevented. If an fsck fixes it, that implies corruption to me. One instance I can imagine where this might happen is where a parent directory is deleted or lost, and it's contents were not (corruption or failed operation). If it was restored in an fsck, that would result in a later placement of ".." in it's subdirectories, I imagine.
kbenson
There are filesystems that don't store directory entries in an ordered list, and that don't return `.` and `..` at any particular position under normal operation. For example, ext3/ext4 with B-trees enabled, which is used on most recent-ish Linux installations.
Gilles
+5  A: 

The order is down to the OS and is explicitly not otherwise defined.

They're easy enough to filter out.

   opendir MYDIR, "$dir";
   my @FILES = grep !/^\.\.?$/, readdir MYDIR  ;
   closedir MYDIR;
Penfold
I'd change your regex for betterr eadability a bit: `my @FILES = grep !/^[.]{1,2}$/, readdir MYDIR;`
DVK
@DVK I actually like `^[.][.]?\z`, but then I am weird like that. Just make sure you anchor at the end of the string using `\z` not `$`.
Sinan Ünür
Yes... beware that `/^\.\.?$/` also matches "..\n", which *is* a legal name that you do *not* want to skip.
Randal Schwartz
+5  A: 

Use File::Slurp::read_dir which, by default, returns a list that does not include . and ...

Sinan Ünür