我需要对目录的所有文件执行我的脚本(搜索)。以下是有效的方法。我只是问哪个是最好的。 (我需要表单的文件名:parsedchpt31_4.txt)
水珠:
my $parse_corpus; #(for all options)
##glob (only if all files in same directory as script?):
my @files = glob("parsed"."*.txt");
foreach my $file (@files) {
open($parse_corpus, '<', "$file") or die $!;
... all my code...
}
readdir with while和conditions:
##readdir:
my $dir = '.';
opendir(DIR, $dir) or die $!;
while (my $file = readdir(DIR)) {
next unless (-f "$dir/$file"); ##Ensure it's a file
next unless ($file =~ m/^parsed.*\.txt/); ##Ensure it's a parsed file
open($parse_corpus, '<', "$file") or die "Couldn't open directory $!";
... all my code...
}
readdir with foreach and grep:
##readdir+grep:
my $dir = '.';
opendir(DIR, $dir) or die $!;
foreach my $file (grep {/^parsed.*\.txt/} readdir (DIR)) {
next unless (-f "$dir/$file"); ##Ensure it's a file
open($parse_corpus, '<', "$file") or die "Couldn't open directory $!";
... all my code...
}
文件::查找:
##File::Find
my $dir = "."; ##current directory: could be (include quotes): '/Users/jon/Desktop/...'
my @files;
find(\&open_file, $dir); ##built in function
sub open_file {
push @files, $File::Find::name if(/^parsed.*\.txt/);
}
foreach my $file (@files) {
open($parse_corpus, '<', "$file") or die $!;
...all my code...
}
还有其他方法吗?将我的整个脚本包含在循环中是否合适?可以,我不使用closedir吗?我把它传递给其他人,我不确定他们的文件在哪里(可能无法使用glob)
非常感谢,希望这是一个正确的问题。
答案 0 :(得分:4)
最佳或最有效的方法取决于您的目的和更大的背景。在原始速度,代码简单性或其他方面,你的意思是最好的吗?我怀疑内存考虑应该推动这种选择。目录中有多少个文件?
纯粹的实用性,glob
方法运作良好。在诉诸任何涉及的问题之前,我会问是否存在问题。
如果你能够使用其他模块,另一种方法是让别人担心肮脏的细节:
use File::Util qw();
my $fu = File::Util->new;
my @files = $fu->list_dir($dir, qw(--with-paths --files-only));
请注意File::Find
执行递归搜索,降序到所有子目录。很多时候你不想要或不需要它。
我还要补充一点,我不喜欢你的两个readdir
例子,因为它们混合了不同的功能:(1)获取文件名,(2)处理单个文件。我会将这些工作分开。
my $dir = '.';
opendir(my $dh, $dir) or die $!; # Use a lexical directory handle.
my @files =
grep { -f }
map { "$dir/$_" }
grep { /^parsed.*\.txt$/ }
readdir($dh);
for my $file (@files){
...
}
答案 1 :(得分:1)
我认为使用while
循环是更安全的答案。为什么?因为将所有文件名加载到数组中可能意味着大量使用内存,并且使用逐行操作可以避免此问题。
我更喜欢readdir
到glob
,但这可能更多的是品味问题。
如果性能存在问题,可以说对于-f
扩展名的任何文件都不需要进行.txt
检查。
答案 2 :(得分:1)
我发现使用完美合作伙伴opendir
/ readdir
和File::chdir
(我最喜欢的CPAN模块,非常适合跨平台)的递归目录行走功能可以让人轻松清晰如果需要,可以操作包含子目录的目录中的任何内容(如果没有,省略递归)。
示例(一个简单的深ls
):
#!/usr/bin/env perl
use strict;
use warnings;
use File::chdir; #Provides special variable $CWD
# assign $CWD sets working directory
# can be local to a block
# evaluates/stringifies to absolute path
# other great features
walk_dir(shift);
sub do_something {
print shift . "\n";
}
sub walk_dir {
my $dir = shift;
local $CWD = $dir;
opendir my $dh, $CWD; # lexical opendir, so no closedir needed
print "In: $CWD\n";
while (my $entry = readdir $dh) {
next if ($entry =~ /^\.+$/);
# other exclusion tests
if (-d $entry) {
walk_dir($entry);
} elsif (-f $entry) {
do_something($entry);
}
}
}