5

Perl で find コマンドを発行し、結果のファイル パスをループ処理したいと考えています。私はそのようにしようとしています(しかし、運がありません):

my $cmd;

open($cmd, '-|', 'find $input_dir -name "*.fastq.gz" -print') or die $!;

while ($line = <$cmd>) {
   print $line;
}

close $cmd;

何か案は?

ありがとう

4

4 に答える 4

4

*キャラクターに十分なエスケープを適用していません。の前に\付けると修正されます。

引数を分離して、そもそもシェルを呼び出さない方がよいでしょう。

use warnings;
use strict;

open(my $cmd, '-|', 'find', $input_dir, '-name' ,'*.fastq.gz', '-print') or die $!;

while (my $line = <$cmd>) {
   print $line;
}

close $cmd;
于 2012-11-15T16:59:35.340 に答える
3

あなたの問題は一重引用符を使用しているようです。変数は補間されませんが、変数名はそのままフィードさ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ます。

于 2012-11-15T17:11:11.950 に答える
2

あなたがするなら

print 'find $input_dir -name "*.fastq.gz" -print';

問題は明らかになるはずです。一重引用符は補間しません。あなたはおそらくするつもりだった

open(my $cmd_fh, '-|', qq{find $input_dir -name "*.fastq.gz" -print}) or die $!;

しかし、それもバグです。$input_dirシェルリテラルに変換しません。2つの解決策があります。

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 $!;
于 2012-11-15T17:08:37.413 に答える
2

コマンドの出力を読み取るには、バックティック演算子を使用します。

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 (コア モジュール) がニーズに合うはずです。

于 2012-11-15T18:07:16.513 に答える