我正在编写一个简单的程序来检查目录中是否存在文件。该文件由一些外部程序创建,没有统一的时间。所以,我需要在循环中检查文件是否存在,因为我需要在它出现时立即处理它。
即使文件已创建,该程序也会持续运行。
#!/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;
我想知道这两种方法的区别。为什么前者没有工作,即使我每次都在循环中读取目录。为什么我每次都需要在循环中打开目录才能使它工作?
答案 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;