Perl的'readdir'功能结果顺序?

Han*_*man 4 perl readdir

我在Windows中运行Perl,我使用readdir获取目录中所有文件的列表,并将结果存储在数组中.数组中的前两个元素似乎总是"." 和"......".这个订单是否有保证(假设操作系统没有改变)?

我想执行以下操作来删除这些值:

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
Run Code Online (Sandbox Code Playgroud)

但我担心这样做可能不安全.我见过的所有解决方案都使用了数组中每个元素的正则表达式或if语句,如果我不需要,我宁愿不使用这些方法.思考?

Sch*_*ern 10

订单无法保证readdir.文档说明了......

返回由打开的目录的下一个目录条目opendir.

整个过程是按文件系统提供的顺序逐步浏览目录中的条目.无法保证此订单可能是什么.

解决这个问题的常用方法是使用正则表达式或字符串相等.

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

my @dirs = grep { $_ ne '.' && $_ ne '..' } readdir $dh;
Run Code Online (Sandbox Code Playgroud)

因为这是一个常见的问题,我建议使用Path::Tiny->children而不是自己滚动.他们会想通了最快和最安全的方式做到这一点,这是用grep过滤掉....Path :: Tiny修复了很多关于Perl文件和目录处理的事情.

  • @HansGoldman它可以在Windows上正常工作.通过"不适用于ActivePerl"我假设你的意思是没有PPM吗?PPM存储库通常是不完整的并且过时了......但是[这里](https://code.activestate.com/ppm/Path-Tiny/)它甚至是最新的.如果它不存在,Path :: Tiny是一个纯Perl模块,可以安装在ActivePerl上.还可以考虑切换到[Strawberry Perl](http://strawberryperl.com/),它带有自己正确配置的编译器和CPAN套件,并且与更多CPAN兼容. (2认同)

mob*_*mob 9

这个perlmonks线程从2001年调查了这个问题,而Perl向导Randal Schwartz总结道

Unix上的readdir返回基础原始目录顺序.对目录使用和释放插槽的添加和删除.任何目录的前两个条目始终创建为"dot"和"dotdot",并且在正常操作下永远不会删除这些条目.

但是,如果其中任何一个的目录条目被错误地删除(通过损坏,或者使用perl -U选项并让超级用户取消链接,例如),则下一个fsck运行必须重新创建条目,它只会添加它.糟糕,点和dotdot不再是前两个条目!

因此,防御性编程要求您不要依赖于插槽顺序.并且没有承诺dot和dotdot是前两个条目,因为Perl无法控制它,并且底层操作系统也不承诺它.