Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I can't work out how to print $status while the external command is running, it always waits for the command to complete.

$status = `c:/oggenc.exe c:/test.wav"`;
print "status: $status\n";

or
open (OGG, "c:/oggenc.exe c:/test.wav |" );
while(<-OGG->)print $_;}

don't work (please ignore the - characters around ogg). does anyone have any ideas? I have looked through loads of nodes re: command output but there is nothing I can find related.

Replies are listed 'Best First'.
Re: running status
by jlongino (Parson) on Jan 12, 2002 at 22:51 UTC
    You cannot do what you are trying via $status whether you use backticks or the system command.

    When executed via backticks you will get the results of the program execution, but not until the command finishes executing.

    When $status is used with system, the only thing returned is the error code.

    What you probably want to do is to run the command as a piped process using open. Here is a very simple example, but you can find more complex examples in either the Programming Perl, Third Edition or Perl Cookbook:

    open OGGENC, "c:/oggenc.exe c:/test.wav|" or die "Can't open oggenc.ex +e $!";
    This will allow you to read the output of the program as it is running instead of after it's done. HTH.

    --Jim

    Update: D'oh! Didn't see that you had tried the example, however, it should work for you. Show us your code as maybe there is an error that we can help fix. Also, you're not testing for errors on the open statement and that may provide useful information.

      the code i put above using open() still waits for the external command to finish. ommitted error checking I know but the oggenc.exe opens ok. i've come across another problem too. the actual output at the end of it isn't even the full output of the program anyway! i think i may be barking up the wrong tree here, I think I need to find out how to interface to the ogg vorbis encoder DLL library. there is an ogg::vorbis library but this doesn't support encoding which is obviously what I'm after.
        A couple of other things:
        • It may be the wrong approach since if it does produce a spinning slash, you will have to wade through a ton of garbage to find what you want. You might want to try putting a "$|++;" at the top of your program to see if this helps (as you may have a buffering problem see Suffering from Buffering? by our own Dominus).
        • As far as the console (DOS) window, here is a good thread with many viable solutions.

        --Jim

        Update: Fixed "thread" link.

Re: running status
by metadoktor (Hermit) on Jan 12, 2002 at 23:23 UTC
    The problem here is that backticks do not work properly under DOS. What you want to do is to issue the system() call like this:
    system("c:\oggenc.exe c:test.wav");
    
    This will output directly to the screen as your program runs.

    As an aside, if you were under UNIX you could have done the following and it does work. It also works under Cygwin.

    `program > /dev/tty`;
    

    I would have thought that you could have done the same thing under Windows using CON, like this:

    `c:\oggenc.exe c:test.wav > CON:`;
    
    But it DOES NOT work. I believe this is a flaw in the way that the ActiveState Perl handles command execution.

    metadoktor

    "The doktor is in."

      i think you missunderstand. i can use the system command and info is outputted to the screen ok but what i am trying to do is have the ability to look at avariable and see, for example when a file is 50% done then do something if it is like pop up a perl/tk message saying "50% done" or something. so you don't have to look at the dos box.
        Ok, I see your point. You want to read the output as it's happening?

        Unfortunately, it seems like the ActiveState version of Perl does not accept file redirection. You could download and install Cygwin along with it's distribution of perl. Then you would be able to run the following script which would probably do what you want.

        # Execute program and put it in the background. system("program > out.txt &"); # Wait for file to be created otherwise this will fail. sleep 3; open(IFILE,"<out.txt") or die "Couldn't open file. $!\n"; # Keep reading until nothing more to read. while (<IFILE>) { # Do something with output. print "$_\n"; } close(IFILE);

        metadoktor

        "The doktor is in."