2012-11-15 11 views
5

ढूंढें मैं परिणामस्वरूप फ़ाइल पथों के माध्यम से पर्ल और लूप में खोज कमांड जारी करना चाहता हूं। मैं ऐसा करने की कोशिश कर रहा हूं (लेकिन कोई भाग्य नहीं है):लूप कमांड का आउटपुट

my $cmd; 

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

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

close $cmd; 

कोई विचार?

धन्यवाद

उत्तर

2

(अद्यतन: मूल जवाब नीचे Ikegami की टिप्पणी की वजह से फिर से काम।)

आपके पास पर्याप्त आवेदन नहीं कर रहे हैं * चरित्र से बचने। \ तैयार करना इसे ठीक करना चाहिए।

यह पहली जगह, में खोल आह्वान करने के लिए नहीं बेहतर है तर्क को अलग करके:

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'; 

करने के लिए समस्या स्पष्ट हो जाना चाहिए थे, तो एकल उद्धरण interpolate मत करो। आप शायद

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

लेकिन यह भी छोटी है। आप शेल शाब्दिक में $input_dir को परिवर्तित नहीं करते हैं। दो समाधान खुद को पेश करते हैं।

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 नहीं है, तब तक हम subroutine से बाहर निकलें (वापस लौटें), अन्यथा हम फ़ाइल नाम को सापेक्ष पथ से प्रिंट करते हैं।

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

धन्यवाद। मुझे यह पसंद है कि यह कितना आसान है –