2012-11-15 18 views
5

Bul komutunu Perl'de vermek ve sonuçta ortaya çıkan dosya yollarıyla döngü oluşturmak istiyorum. Denemeye çalışıyorum (ancak hiç şansınız yok):Döngü Bulma Komutunun Çıktısı

my $cmd; 

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

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

close $cmd; 

Herhangi bir fikrin var mı?

Teşekkür

cevap

2

(Güncelleme: çünkü aşağıda Ikegami yorumun yeniden işlenmiş orijinal bir cevap.)

Sen * karaktere kaçan yeterince uygulayarak değiliz. Bir \ ürününün hazırlanması düzeltilmelidir. Eğer sorun bariz haline gelmelidir

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

yapmak olsaydı

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

Haklısınız ve bunu test etmeliydim. Cevabımı buna göre değiştiriyorum. – reinierpost

2

:

Bu argümanlar ayırarak ilk etapta, yılında kabuk çağırmak için daha iyidir Tek tırnak interpolasyon yapmayın. Muhtemelen

yapmak istiyorsunuz, ama bu da buggy. $input_dir'u bir kabuk haline dönüştürmezsiniz. İki çözüm kendini gösterir.

use String::ShellQuote qw(shell_quote); 

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

Ya

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

Senin sorunun tek tırnak kullanarak gibi görünüyor. Değişkeniniz enterpole edilmeyecek, ancak değişken adı olduğu gibi find'a gönderilecektir.

Ancak neden File::Find kullanılmıyor? İşte

> 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 altyordamı basitçe dosya adı karşı bir desen eşleşme. Uzantı .pl değilse, altprogramdan çıkarız (geri dönüş), aksi takdirde dosya adını göreceli yolla yazdırırız.

2

Bir komutun çıktısını okumak için backtick operator'u kullanın.

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 
} 

ben çok daha iyi okunabilir boru daha olduğunu düşünüyorum. Dezavantajı engeller, bu yüzden çok sayıda hat ile büyük çıkış dizilerini işlemek istiyorsanız, boru yaklaşımı daha iyi olabilir.

Ancak uygun bir modül kullanmak isteyebilirsiniz. File::Find (çekirdek modül) ihtiyaçlarınızı karşılamalıdır.

+1

Teşekkürler. Bunun ne kadar basit olduğunu seviyorum –