我有一个包含数百个文件的目录dir1
,这些文件将由名为HRest的语音程序迭代处理。该程序应该逐个获取每个文件,处理它并将其放在新目录中(如dir2
进行第一次迭代),以便在下一次迭代中使用。我的问题是,我不知道我采用的方式来遍历dir1
中的文件,以及我运行脚本(trainhmms.pl dir1 1)
的方式是否正确。< / p>
如果dir1中的文件是L1,L2,L3,...,L500,我希望HRest
执行为
HRest -T 1 -I timedlabels_train.mlf -t -i 20 -l dir1/L1 -M dir2 -S train.scp
表示第一个文件,
HRest -T 1 -I timedlabels_train.mlf -t -i 20 -l dir1/L2 -M dir2 -S train.scp
表示下一个文件,依此类推所有文件。然后在下一次调用脚本时,我希望将其更改为
HRest -T 1 -I timedlabels_train.mlf -t -i 20 -l dir2/L1 -M dir3 -S train.scp
表示第一个文件,依此类推..
这是第一次迭代的脚本:
#!/usr/bin/perl
use File::Slurp;
# Usage: trainhmms.pl dir1 1
# dir1: Folder containing models after being initialised by HInit (L1,L2,..,L512)
$file = $ARGV[0];
$iter = $ARGV[1];
my @files = read_dir '/Users/negarolfati/Documents/Detection_rerun/AF_TIMIT/1_state//trainHMMs/dir1';
for my $file ( @files ) {
$iter2 = $iter+1;
$cmd = "HRest -T 1 -I timedlabels_train.mlf -t -i 20 -l '$dir[$iter]/$file' -M '$dir[$iter2]' -S train.scp ";
system("$cmd");
}
答案 0 :(得分:3)
您不能只在目录字符串上使用 readdir
。您必须opendir
字符串,然后从您获得的目录句柄readdir
,最后closedir
句柄。
您还必须记住readdir
返回目录名称和文件名,以及伪目录。要仅过滤掉文件,可以使用.
和..
-f
测试运算符。对于您正在阅读的目录,chdir
通常最方便,这样您就不必在执行测试之前将readdir
返回的每个文件名附加到路径。
我不知道HRest
是什么,但如果您的命令行必须从特定的工作目录(可能是acccess timedlabels_train.mlf
和train.scp
)执行,那么请说明。我将不得不删除chdir
声明。
这样的事情会让你前进。我使用了autodie
,它自动检查文件系统操作。每次使用chdir
时,每次明确检查opendir
和or die $!
都可以节省费用。
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
use File::Spec::Functions 'catdir';
my ($file, $iter) = @ARGV;
my $root = '/Users/negarolfati/Documents/Detection_rerun/AF_TIMIT/1_state/trainHMMs';
my $dir1 = catdir $root, 'dir'.$iter;
my $dir2 = catdir $root, 'dir'.($iter+1);
chdir $dir1;
opendir my ($dh), '.';
my @files = grep -f, readdir $dh;
closedir $dh;
for my $file ( @files ) {
my $cmd = "HRest -T 1 -I timedlabels_train.mlf -t -i 20 -l '$dir1/$file' -M '$dir2' -S train.scp";
system($cmd);
}
<强>更新强>
这是一个避免chdir
的替代版本,以便当前工作目录保持不变。
我添加了bash脚本中的辅助循环。我还添加了一个print
语句,以便您可以在执行之前查看每个命令。
要允许system
调用继续,只需删除或注释掉next
语句。
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
use File::Spec::Functions qw/ catdir catfile /;
STDOUT->autoflush;
my $root = '/Users/negarolfati/Documents/Detection_rerun/AF_TIMIT/1_state/trainHMMs';
for my $iter (1 .. 4) {
my $dir1 = catdir $root, 'dir'.$iter;
my $dir2 = catdir $root, 'dir'.($iter+1);
opendir my ($dh), $dir1;
while (my $node = readdir $dh) {
my $file = catfile($dir1, $node);
next unless -f $file;
my $cmd = "HRest -T 1 -I timedlabels_train.mlf -t -i 20 -l '$file' -M '$dir2' -S train.scp";
print $cmd, "\n";
next; # Remove for full functionality
system($cmd);
}
closedir $dh;
}
答案 1 :(得分:-1)
你可以这样做:
my @files = <$path/*>;
foreach my $filename ( reverse(@files) ) {
...
}