2012-11-15 13 views
5

Chcę, aby wydać polecenie find w Perlu i pętli przez ścieżki plików wynikowych. Próbuję tego (ale nie mając szczęścia):Pętla Znajdź wyjście polecenia

my $cmd; 

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

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

close $cmd; 

Jakieś pomysły?

Dzięki

Odpowiedz

2

(Aktualizacja: oryginalna odpowiedź przerobione z powodu komentarza Ikegami jest poniżej).

nie jesteś wystarczająco stosowania ucieczce do charakteru *. Po dodaniu \ należy to naprawić.

Lepiej nie wywołuje powłoki na pierwszym miejscu, przez oddzielenie argumenty:

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

Masz rację, i powinienem był to sprawdzić. Odpowiednio modyfikuję swoją odpowiedź. – reinierpost

2

Jeśli było zrobić

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

Problem powinien stać się oczywiste: Single-cytaty nie interpoluj. Prawdopodobnie chciałeś zrobić

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

ale to też jest błędne. Nie konwertujesz $input_dir na literał powłoki. Przedstawiają się dwa rozwiązania.

use String::ShellQuote qw(shell_quote); 

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

Albo

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

Twój problem wydaje się być za pomocą apostrofów. Twoja zmienna nie zostanie interpolowana, ale nazwa zmiennej zostanie podana jako find.

Ale dlaczego nie używać 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 

Tutaj wanted podprogram jest po prostu mecz wzór do nazwy pliku. Wyjście (powrót z) podprogramu, chyba że rozszerzenie to .pl, w przeciwnym razie wydrukujemy nazwę pliku ze ścieżką względną.

2

Aby odczytać wynik polecenia, należy użyć 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 
} 

Myślę, że jest o wiele lepiej czytelny niż orurowanie. Minusem jest to, że blokuje, więc jeśli chcesz przetworzyć olbrzymie ciągi wyjściowe z dużą ilością linii, podejście rurowe może być lepsze.

Ale możesz chcieć użyć odpowiedniego modułu. File::Find (moduł podstawowy) powinien pasować do twoich potrzeb.

+1

Dziękuję. Podoba mi się, jak prosty jest ten –

Powiązane problemy