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

i am in need for parsing output of a dd function within perl. the dd utility typically spits out transfer speeds (x.x Mbytes transferred in y.yyy seconds). How do i capture this output of the dd command? i am doing a whole bunch of dd's. hence i need to capture all the results to average it. thanks!

Replies are listed 'Best First'.
Re: dd related
by grep (Monsignor) on Mar 27, 2002 at 00:50 UTC

    Check out perlop and the ` backtick or qx operator. These run a command and capture the output.

    Like this:
    my @return = `ls -l`;

    This is also a FAQ. Try running 'perldoc -q capture' from your commandline and you will see this FAQ.

    Perldoc has many useful features besides the '-q' for FAQ keywords, you can find them by just running 'perldoc'



    grep
    grep> cd /pub
    grep> more beer
Re: dd related
by CukiMnstr (Deacon) on Mar 27, 2002 at 01:50 UTC
    another option is to assign the output of the command to a filehandle, and then <> it. check open() for the details, but basically you can do:
    open(DD, "/bin/dd $dd_options |"); while ($line = <DD>) { # do whatever with the output of dd, one line at a time ... }
    hope this helps.

      Hi,
      Is there any difference between the backticks and the process open
      which you have just demonstrated?
      I mean, does perl internally implement it differently?
      For eg. A backtick may be passed to the shell directly
      while the open(as above) may be implemented using popen,
      which involves creating a pipe, forking, and invoking
      the shell.
      Or does perl just execute the command and then provide you
      with a line by line output as you read it.

      Thanx
      --
      arc_of_descent
        > Is there any difference between the backticks and the process open which you have just demonstrated?
        A quick glance over the perlipc manpage reveals they that are similar in intent. They both fork and execute the process, but open() ...
        ... gives you finer control of the whole process, letting you to kill off the child process early if you'd like.
        So you might use open() if you want to exit from the process early in order to avoid unnecessary overhead.
        HTH

        broquaint

Re: dd related
by petral (Curate) on Mar 27, 2002 at 14:51 UTC
    These are all answers which give useful techniques for the general case.   But note that the status info which anair wishes to parse is written to stderr!

      p
Re: dd related
by Util (Priest) on Mar 27, 2002 at 18:31 UTC

    As petral pointed out, dd outputs its status messages on STDERR, not on STDOUT, but open and backticks only capture STDOUT. You can get around this by redirecting STDERR into the STDOUT file handle; the syntax is the same as on the shell command line, because Perl calls the Bourne shell to set up the redirection:
    dd if=infile of=outfile 2>&1 Example Perl code:

    my @r = `dd if=infile of=outfile 2>&1`; foreach (@r) { chomp; print "***$_***\n"; }
    My dd on Linux does not output transfer speeds, just Records+PartialRecords in and out, so the program above printed:
    ***0+1 records in*** ***0+1 records out***

    Note that this only works correctly when you use the of parameter of dd. If you redirect STDOUT using the shell instead, then Perl will not see the status messages, because they get embedded somewhere in the output file. For example:

    # BAD CODE my @r = `dd if=infile >outfile 2>&1`;

    I wrote this to give a dd specific example. In the perlfaq pointer (How can I capture STDERR from an external command?) that grep gave earlier, all the permutations of STDOUT vs. STDERR and open vs. backticks are discussed.