2012-11-15 12 views
5

私はPerlでfindコマンドを発行し、結果のファイルパスをループしたいと思っています。私はそれをそうしようとしています(運がありません):Loop Findコマンドの出力

my $cmd; 

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

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

close $cmd; 

アイデアはありますか?

おかげ

答えて

2

(更新:理由は以下の池上さんのコメントを作り直し、元の答え。)

あなたは*文字に逃げる十分に適用していません。 \を先行すると修正されます。

それは引数を分離することにより、最初の場所、 でシェルを起動しない方が良いです。

use warnings; 
use strict; 

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

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

close $cmd; 
+0

あなたはそうです。これをテストしたはずです。私はそれに応じて私の答えを変更しています。 – reinierpost

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 $!; 
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でないかぎり、サブルーチンを終了(戻り)します。そうでなければ、相対パスでファイル名を出力します。

2

コマンドの出力を読み取るには、backtick operatorを使用します。

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(コアモジュール)は、お客様のニーズに合わせてください。

+1

ありがとうございます。私はこのシンプルさがいかに単純か –

関連する問題