Using tee with Perl's system command

O

olson_ord

Hi,
I want to call/run another program with a perl script - and I need
to look at the current output on the screen and at the same time I need
this output dumped to a file. Without using perl I would just use tee.
However within perl it seems that its having some problem with the pipe
symbol "|".

As an example I have subsituted ls for my actual program and its
arguments (it has many of these). My script looks something like

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

my @args = ("ls", "|", "tee", "out.txt");
print "\n\nExecuting @args \n";
system (@args) == 0 or die "System @args failed: $? \n";
---------------------------------------------------------------------

The output that I receive from the command line is something like


Executing ls | tee out.txt
ls: |: No such file or directory
ls: tee: No such file or directory
out.txt
System ls | tee out.txt failed: 256

I know that tee and | are not arguments to ls. However if I execute
this using back ticks then I don't get the output on the screen - so
thats not an option.

Thanks a lot for taking your time to help me.
O.O.
 
J

Jürgen Exner

use tee. However within perl it seems that its having some problem
with the pipe symbol "|".

my @args = ("ls", "|", "tee", "out.txt");
system (@args) == 0 or die "System @args failed: $? \n";

But you are explicitely asking perl to hand those values as arguments to ls.

See first paragraph of "perldoc -f system" how to have the system shell
execute the command line.

jue
 
O

olson_ord

Ok I agree with what you say and I even pointed this out in my own post
i.e. its seeming that I am passing these as arguments to ls.
After reading your post I just tried passing everything to system
using just one string i.e. system("ls | tee out.txt"); - and this
works. As mentioned in my original post I tried everything but I forgot
that I could pass the entire thing as a string without breaking it up
into arguments.
Thanks a lot.
O.O.
 
T

Ted Zlatanov

I want to call/run another program with a perl script - and I need
to look at the current output on the screen and at the same time I need
this output dumped to a file. Without using perl I would just use tee.
However within perl it seems that its having some problem with the pipe
symbol "|".

I would consider opening ls as a pipe:

open F, "ls|" or die "Couldn't open ls pipe: $!";
open W, ">out.txt" or die "Couldn't write to out.txt: $!";

while (<F>)
{
print;
print W $_;
}

In addition, opendir/readdir/stat ( see "perldoc -f readdir" and
others) are probably more precisely what you need.

In general, you should avoid using the shell to do *simple* things
that Perl can do (grep, ls, ps, awk, etc.). You'll pay a penalty in
every way otherwise.

Ted
 
O

olson_ord

Jim said:
Jürgen fixed your problem with system. However, I would like to point
out that another solution is to capture the output of the external
program using backticks and then write the lines to the screen and also
to a file from with your Perl program.

Thanks Jim for taking the time to respond. I thought of this solution
- but I want some way to know what the program is currently doing.
Executing it with backticks waits for the completion of the execution
before proceeding to dump output on the screen.
Regards,
O.O.
 
O

olson_ord

Ted said:
I would consider opening ls as a pipe:

open F, "ls|" or die "Couldn't open ls pipe: $!";
open W, ">out.txt" or die "Couldn't write to out.txt: $!";

while (<F>)
{
print;
print W $_;
}

In addition, opendir/readdir/stat ( see "perldoc -f readdir" and
others) are probably more precisely what you need.

In general, you should avoid using the shell to do *simple* things
that Perl can do (grep, ls, ps, awk, etc.). You'll pay a penalty in
every way otherwise.

Ted

Thanks Ted for taking the time to respond. Here ls is just used as an
example command - but I am actually calling one of my own executables
here. I just wanted to provide a working example.
I think this code suggested also has the property that it would just
dump everything out after the execution. I don't want this because I
want to see where my code gets stuck - in case of a crash in one of
my test cases.
Regards,
O.O.
 
T

Ted Zlatanov

Thanks Ted for taking the time to respond. Here ls is just used as an
example command - but I am actually calling one of my own executables
here. I just wanted to provide a working example.

Oh, OK.
I think this code suggested also has the property that it would just
dump everything out after the execution. I don't want this because I
want to see where my code gets stuck - in case of a crash in one of
my test cases. Regards, O.O.

If you mean that you want STDERR as well (where errors are typically
printed in Unix), you need to redirect it. Look at "perldoc -q STDERR"
for specifics.

If you want the script to immediately output what it gets from the
command, set $| to 1 ("perldoc -q flush"). Otherwise the Perl output
is buffered so you won't necessarily get every line as it's printed by
the script. If the command buffers its output, that's a different
problem that Perl won't solve :)

Ted
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top