views:

596

answers:

7

I want to have output of Windows command-line program (say, powercfg -l) written into a file which is created using Perl and then read the file line by line in a for loop and assign it to a string.

+9  A: 
system 'powercfg', '-l';

is the recommended way. If you don't mind spawning a subshell,

system "powercfg -l";

will work, too. And if you want the results in a string:

my $str = `powercfg -l`;
wallenborn
Better answer than mine
Xetius
Don't forget to check the return value from the system call.
Craig
@craig: Is there a way to check the return value AND capture the output in a string?
jimtut
Use backticks and check $? afterwards.
innaM
If you want to capture the output without spawning a subshell: `open my $pipe, '-|', qw(powercfg -l) or die; my @output = <$pipe>; close $pipe;`
ephemient
open '-|' also spawns a subshell
mobrule
Hi,How to capture the command result in a string??The above mentioned are not working!! Please suggest some other way to get this done ?
stack_pointer is EXTINCT
Why are they not working? What's the error message? What is the output of `$str=\`powercfg -l\`; print "Return code: $?\n"; print $str,"\n";` ?
wallenborn
Hi ppl....I still cant assign the command output to a string: consider the follwing Perl PROGRAM in VIsta where i've used the DOS command -my $str=sytem "powercfg -l";print $strOUTPUT::%%% Output of the DOS command %%% 0here the value of the string $str is printed as 0.......What do i do ???
stack_pointer is EXTINCT
+1  A: 

Since the OP is running powercfg, s/he are probably capturing the ouput of the external script, so s/he probably won't find this answer terribly useful. This post is primarily is written for other people who find the answers here by searching.

This answer describes several ways to start command that will run in the background without blocking further execution of your script.

Take a look at the perlport entry for system. You can use system( 1, 'command line to run'); to spawn a child process and continue your script.

This is really very handy, but there is one serious caveat that is not documented. If you start more 64 processes in one execution of the script, your attempts to run additional programs will fail.

I have verified this to be the case with Windows XP and ActivePerl 5.6 and 5.8. I have not tested this with Vista or with Stawberry Perl, or any version of 5.10.

Here's a one liner you can use to test your perl for this problem:

C:\>perl -e "for (1..100) { print qq'\n $_\n-------\n'; system( 1, 'echo worked' ), sleep 1 }

If the problem exists on your system, and you will be starting many programs, you can use the Win32::Process module to manage your application startup.

Here's an example of using Win32::Process:

use strict;
use warnings;

use Win32::Process;

if( my $pid = start_foo_bar_baz() ) {
    print "Started with $pid";
}
:w

sub start_foo_bar_baz {

    my $process_object;  # Call to Create will populate this value.
    my $command = 'C:/foo/bar/baz.exe';  # FULL PATH to executable.
    my $command_line = join ' ',
           'baz',   # Name of executable as would appear on command line
           'arg1',  # other args
           'arg2';

    # iflags - controls whether process will inherit parent handles, console, etc.
    my $inherit_flags = DETACHED_PROCESS;  

    # cflags - Process creation flags.
    my $creation_flags = NORMAL_PRIORITY_CLASS;

    # Path of process working directory
    my $working_directory = 'C:/Foo/Bar';

    my $ok = Win32::Process::Create(
       $process_object,
       $command,
       $command_line,
       $inherit_flags,
       $creation_flags, 
       $working_directory,
    );

    my $pid;
    if ( $ok ) {
        $pid = $wpc->GetProcessID;
    }
    else {
        warn "Unable to create process: "
             . Win32::FormatMessage( Win32::GetLastError() ) 
        ;
        return;
    }

    return $pid;
}
daotoad
A: 

Try using > operator to forward the output to a file, like:

powercfg -l > output.txt

And then open output.txt and process it.

erelender
Hi I want to use Perl in this.... as i don't know how to capture the output in a file (to be created) and read that file line by line and assigning the line to a string in the PERL script.
stack_pointer is EXTINCT
+7  A: 

There is no need to first save the output of the command in a file:

my $output = `powercfg -l`;

See qx// in Quote-Like Operators.

However, if you do want to first save the output in a file, then you can use:

my $output_file = 'output.txt';

system "powercfg -l > $output_file";

open my $fh, '<', $output_file 
    or die "Cannot open '$output_file' for reading: $!";

while ( my $line = <$fh> ) {
    # process lines
}

close $fh;

See perldoc -f system.

Sinan Ünür
+1  A: 
my $output = qx(powercfg -l);

## You've got your output loaded into the $output variable. 
## Still want to write it to a file?
open my $OUTPUT, '>', 'output.txt' or die "Couldn't open output.txt: $!\n";
print $OUTPUT $output;
close $OUTPUT

## Now you can loop through each line and
##   parse the $line variable to extract the info you are looking for.
foreach my $line (split /[\r\n]+/, $output) {
  ## Regular expression magic to grab what you want
}
joealba
+1  A: 

To expand on Sinan's excellent answer and to more explicitly answer your question:

NOTE: backticks `` tell Perl to execute a command and retrieve its output:

#!/usr/bin/perl -w
use strict;


my @output = `powercfg -l`;
chomp(@output); # removes newlines

my $linecounter = 0;    
my $combined_line;

foreach my $line(@output){
    print $linecounter++.")";
    print $line."\n"; #prints line by line

    $combined_line .= $line; # build a single string with all lines
    # The line above is the same as writing:
    # $combined_line = $combined_line.$line;
}

print "\n";
print "This is all on one line:\n";
print ">".$combined_line."<";

Your output (on my system) would be:

0)
1)Existing Power Schemes (* Active)
2)-----------------------------------
3)Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e  (Balanced) *
4)Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c  (High performance)
5)Power Scheme GUID: a1841308-3541-4fab-bc81-f71556f20b4a  (Power saver)

This is all on one line:
>Existing Power Schemes (* Active)-----------------------------------Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e  (Balanced) *Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c  (High performance)Power Scheme GUID: a1841308-3541-4fab-bc81-f71556f20b4a  (Power saver)<

Perl makes it easy!

Mick
+1  A: 

You have some good answers already. In addition, if you just want to process a command's output and don't need to send that output directly to a file, you can establish a pipe between the command and your Perl script.

use strict;
use warnings;

open(my $fh, '-|', 'powercfg -l') or die $!;
while (my $line = <$fh>) {
    # Do stuff with each $line.
}
FM
There is no need for the defined test when reading from a file handle in a while statement. See the output of `perl -MO=Deparse -e "print while <>"`
Sinan Ünür
@Sinan Thanks a lot. I was not familiar with `-MO=Deparse`. Very useful.
FM