Path::Class::Dir の children が「0」で止まること

Path::Class::Dir の recurse メソッドを使っていて、なぜか走査されないディレクトリがある。具体的には、サブディレクトリとして 0/, 1/, 2/, ..., e/, f/ があるのだが、0/ と 1/ と f/ の下のファイルが走査されない。試しに children で一覧してみると、やはり 0/, 1/, f/ が表示されない。Path::Class::Dir のソースを見ると、recurse は children を呼んでいるから、根っこは同じはず。試しに再度ディレクトリを作りなおしても同じ現象。

どうやら Path::Class::Dir-0.16のchildrenが「0」で止まる件 - Unknown::Programming、ということらしい。正しい対処はバグを報告して直してもらうこと。とりあえずの回避策としては、仕様を変更して 0/ というディレクトリ名をやめること。

ところで、ディレクトリを作りなおしても同じディレクトリが出力されないってことは、children がディレクトリ名 (i-node 番号とかでなく) として順序を保持しているということを示唆している。順不同、環境依存だと思っていたけれど、とりあえず私が実行している環境では一覧される順番に再現性がある。Path::Class::Dir のソースを見ると、children は IO::Dir の read メソッドで出力される順に依存している。IO::Dir のソースを見ると、Perl の組込み関数 readdir を呼び出しているだけだった。さらに Perl のソースも潜ってみたけれど、ちょっとすぐにはわからなかった。

そっか。文字列「0」は偽値なんだね。

use strict;
use warnings;

warn "--- IO::Dir ---";
use IO::Dir;
my $dh = new IO::Dir('test/');
while (defined(my $c = $dh->read)) {
    warn $c ? "[$c]" : "-$c-";
}

warn "--- Path::Class ---";
use Path::Class;
my $dir = dir('test/');
foreach my $c ($dir->children) {
    warn $c;
}

実行結果。

--- IO::Dir --- at a.pl line 4.
[-0] at a.pl line 8.
[00] at a.pl line 8.
[..] at a.pl line 8.
[0e1] at a.pl line 8.
[g] at a.pl line 8.
[0x0] at a.pl line 8.
[2] at a.pl line 8.
-0- at a.pl line 8.
[1] at a.pl line 8.
[f] at a.pl line 8.
[.] at a.pl line 8.
--- Path::Class --- at a.pl line 11.
test/-0 at a.pl line 15.
test/00 at a.pl line 15.
test/0e1 at a.pl line 15.
test/g at a.pl line 15.
test/0x0 at a.pl line 15.
test/2 at a.pl line 15.