2016-09-28 95 views
0

我在寫一個簡單的程序來檢查目錄中是否存在文件。該文件由一些沒有統一時間的外部程序創建。所以,我需要檢查一個循環中是否存在文件,因爲我需要在文件一出現就處理它。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; 

我想知道這兩種方法的區別。爲什麼前一個沒有工作,即使我每次都在循環讀取目錄。爲什麼我需要在循環中每次打開目錄才能使其工作?

+0

它確實如此。 – AbhiNickz

+1

看看[Filesys :: Notify :: Simple](https://metacpan.org/pod/Filesys::Notify::Simple)。 – nwellnhof

回答

6

這是因爲在readdir之後,目錄句柄到達文件列表的末尾,因此即使在此期間添加了一個文件,下次也沒有更多內容可以讀取。在列表上下文中使用句柄時,會在第一次讀取時發生。

您可以將一個調用rewinddir添加到循環中,該循環將目錄句柄移回到下一個readdir的目錄開頭。

或者,使用glob並把測試就在until條件

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

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

這樣的目錄重新讀取每個測試。由於glob返回的路徑,這簡化了事情。

它也因爲在第一個程序,您使用的執行opendir一次,然後你想因此它不包含有關文件及在第二程序的最新信息,來讀取舊的$ DH文件縮短到

my @files; 

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

say for @files; 
+0

@ arunesh-singh我更新了答案,評論了爲什麼會發生這種情況,以及另一個代碼片段。 – zdim