我想在 Perl 中发出 find 命令并遍历生成的文件路径。我正在尝试这样(但没有任何运气):
my $cmd;
open($cmd, '-|', 'find $input_dir -name "*.fastq.gz" -print') or die $!;
while ($line = <$cmd>) {
print $line;
}
close $cmd;
有任何想法吗?
谢谢
我想在 Perl 中发出 find 命令并遍历生成的文件路径。我正在尝试这样(但没有任何运气):
my $cmd;
open($cmd, '-|', 'find $input_dir -name "*.fastq.gz" -print') or die $!;
while ($line = <$cmd>) {
print $line;
}
close $cmd;
有任何想法吗?
谢谢
您没有对*
角色进行足够的转义。前置 a\
应该修复它。
最好不要一开始就通过分隔参数来调用 shell:
use warnings;
use strict;
open(my $cmd, '-|', 'find', $input_dir, '-name' ,'*.fastq.gz', '-print') or die $!;
while (my $line = <$cmd>) {
print $line;
}
close $cmd;
您的问题似乎是使用单引号。您的变量不会被插值,但变量名称将按find
原样提供。
但是为什么不使用File::Find
呢?
> perl -MFile::Find -lwe '
$foo = "perl";
find ( sub { /\.pl$/i or return; print $File::Find::name }, $foo);'
perl/foo.pl
perl/parsewords.pl
perl/yada.pl
在这里,wanted
子例程只是针对文件名的模式匹配。我们退出(返回)子程序,除非扩展名是.pl
,否则我们打印带有相对路径的文件名。
如果你要做
print 'find $input_dir -name "*.fastq.gz" -print';
问题应该变得很明显:单引号不会插入。你可能打算做
open(my $cmd_fh, '-|', qq{find $input_dir -name "*.fastq.gz" -print}) or die $!;
但这也有问题。您不会转换$input_dir
为 shell 文字。出现了两种解决方案。
use String::ShellQuote qw( shell_quote );
my $cmd = shell_quote("find", $input_dir, "-name", "*.fastq.gz", "-print");
open(my $cmd_fh, '-|', $cmd) or die $!;
或者
my @cmd = ("find", $input_dir, "-name", "*.fastq.gz", "-print");
open(my $cmd_fh, '-|', @cmd) or die $!;
要读取命令的输出,请使用反引号运算符。
my $command = "find $inputdir ..."; # interpolate the input directory
my $output = `$command`; # be careful here
my @lines = split /\n/ => $output; # split in single lines
for my $line (@lines) { # iterate
# do something with $line
}
我认为它比管道更具可读性。缺点是它会阻塞,所以如果你想处理带有很多行的巨大输出字符串,管道方法可能会更好。
但是您可能想要使用适当的模块。File::Find(核心模块)应该满足您的需求。