Perl:读取目录,直到文件存在

时间:2016-09-28 06:48:46

标签: perl

我正在编写一个简单的程序来检查目录中是否存在文件。该文件由一些外部程序创建,没有统一的时间。所以,我需要在循环中检查文件是否存在,因为我需要在它出现时立即处理它。

即使文件已创建,该程序也会持续运行。

#!/usr/bin/perl
use strict;
use warnings;


my $dir = "/my/path";
opendir( my $dh, $dir ) || die "can't opendir $dir: $!";
my @files = grep { /^[^\.]/ && -f "$dir/$_" } readdir($dh);
until (@files) {
    print "No files Found: Sleeping for a sec\n";
    sleep(1);
    @files = grep { /^[^\.]/ && -f "$dir/$_" } readdir($dh);
}
print @files;

以下程序按预期工作。

#!/usr/bin/perl
use strict;
use warnings;


my $dir = "/my/path";
opendir( my $dh, $dir ) || die "can't opendir $dir: $!";
my @files = grep { /^[^\.]/ && -f "$dir/$_" } readdir($dh);
closedir $dh;
until (@files) {
    opendir( my $dh, $dir ) || die "can't opendir $dir: $!";
    print "No files Found: Sleeping for a sec\n";
    sleep(1);
    @files = grep { /^[^\.]/ && -f "$dir/$_" } readdir($dh);
    closedir $dh;
}

print @files;

我想知道这两种方法的区别。为什么前者没有工作,即使我每次都在循环中读取目录。为什么我每次都需要在循环中打开目录才能使它工作?

1 个答案:

答案 0 :(得分:6)

这是因为在readdir之后,目录句柄到达文件列表的末尾,所以即使同时添加了文件,下次也无需再读取。当在列表上下文中使用句柄时,会在第一次读取时发生这种情况。

您可以向循环添加对rewinddir的调用,这会将目录句柄移回到下一个readdir目录的开头。

或者,使用glob并将测试置于until条件

my $cond = qr(^[^\.]); 

until (grep { $cond && -f } glob "$dir/*") { 
    say "no files"; 
    sleep 1;
}

这样,每次测试都会重新读取目录。由于glob返回路径,这简化了事情。

它也可以缩短为

my @files;

sleep 1 until @files = grep { $cond && -f } glob "$dir/*";

say for @files;