pete@othello.dartmouth.edu (Pete Schmitt) (06/06/91)
Is there a tee like program that will pipe down to another program? -pete schmitt -- Peter Schmitt UNIX Consultant Kiewit Computation Center Computing Services Dartmouth College (603)646-2085 Hanover, NH 03755 Peter.Schmitt@Dartmouth.EDU
dkeisen@leland.Stanford.EDU (Dave Eisen) (06/06/91)
In article <1991Jun6.093939.9346@dartvax.dartmouth.edu> pete@othello.dartmouth.edu (Pete Schmitt) writes: >Is there a tee like program that will pipe down to another program? > Sure. It's called "tee". Something like: program1 | tee /dev/tty | program2 should do what you want. -- Dave Eisen dkeisen@leland.Stanford.EDU 1101 San Antonio Road, Suite 102 Mountain View, CA 94043 (415) 967-5644
Tom Christiansen <tchrist@convex.COM> (06/06/91)
(Put followups wherever you want -- I just didn't want them to land in alt.sources unless they were also source.) From the keyboard of dkeisen@leland.Stanford.EDU (Dave Eisen): :In article <1991Jun6.093939.9346@dartvax.dartmouth.edu> pete@othello.dartmouth.edu (Pete Schmitt) writes: :>Is there a tee like program that will pipe down to another program? :> : :Sure. It's called "tee". : :Something like: : :program1 | tee /dev/tty | program2 : :should do what you want. I suspect that this is not want the original poster wanted. While its true that it does work in this case, it's not going to work if you want to "tee off" to a list of processes. Here's a program that's a supersets of the original tee, so I think you can just put it in your own bin and call it tee; I did.. Instead of just file specs, you can give pipe specs like this "|program". So for the simple suggestion above, the usage would be program1 | tee "|program2" which isn't particularly interesting. This is: program1 | tee "|program2" "|program3" "|program4" It still understands -a for append and -i for ignoring interrupts (which I've never used), as well as a new -u for "unbuffered" output, especially useful with pipes. You can also mix your appends and overwrites by specifying ">>file" for appending. "file" is the same as ">file", unless the -a flag is on, in which case it's ">>file". You can always use ">file" or ">>file" to override the default. For example, not using any defaults: $ prog1 | tee -u ">file1" "|prog2" ">>file2" "|prog3 | prog4" ">file3" ">>file4" prog1 runs into tee, which duplicates its output to several different places. first, a copy goes to stdout (redirect into /dev/null if you don't want this.) file1 and file3 get overwritten, file2 and file4 get appended to, and prog2 and prog3 get run. oh, and prog3 runs into prog4. Program follows; not bad for ~30 lines of code, eh? :-) --tom #!/usr/bin/perl # # tee clone that groks process tees (should work even with old perls) # Tom Christiansen <tchrist@convex.com> # 6 June 91 while ($ARGV[0] =~ /^-(.+)/ && (shift, ($_ = $1), 1)) { next if /^$/; s/i// && (++$ignore_ints, redo); s/a// && (++$append, redo); s/u// && (++$unbuffer, redo); die "usage tee [-aiu] [filenames] ...\n"; } if ($ignore_ints) { for $sig ('INT', 'TERM', 'HUP', 'QUIT') { $SIG{$sig} = 'IGNORE'; } } $mode = $append ? '>>' : '>'; $fh = 'FH000'; %fh = ('STDOUT', 'standard output'); # always go to stdout $| = 1 if $unbuffer; for (@ARGV) { if (!open($fh, (/^[^>|]/ && $mode) . $_)) { warn "$0: cannot open $_: $!\n"; # like sun's; i prefer die $status++; next; } select((select($fh), $| = 1)[0]) if $unbuffer; $fh{$fh++} = $_; } while (<STDIN>) { for $fh (keys %fh) { print $fh $_; } } for $fh (keys %fh) { close($fh) && next; warn "$0: couldn't close $fh{$fh}: $!\n"; $status++; } exit $status; -- Tom Christiansen tchrist@convex.com convex!tchrist "Perl is to sed as C is to assembly language." -me
tchrist@convex.COM (Tom Christiansen) (06/07/91)
It might be nice to get better than an ungraceful death by SIGPIPE if a pipe kid dies or never gets started. Here's a patch to trap this: 16a17 > $SIG{'PIPE'} = 'PLUMBER'; 37c38 < close($fh) && next; --- > next if close($fh) || !defined $fh{$fh}; 41a43,48 > > sub PLUMBER { > warn "$0: pipe to \"$fh{$fh}\" broke!\n"; > $status++; > delete $fh{$fh}; > } --tom -- Tom Christiansen tchrist@convex.com convex!tchrist "Perl is to sed as C is to assembly language." -me
pd@pd@x.co.uk (Paul Davey) (06/07/91)
>>>>> On 6 Jun 91 09:39:39 GMT, pete@othello.dartmouth.edu (Pete Schmitt) said:
Pete> Is there a tee like program that will pipe down to another program?
You can get the effect of this on some machines by using tee and a
named pipe or fifo file. (This is not a general solution.)
to pipe the output from lotsofdataprogram to stream1 and stream2,
mknod fifo p
lotsofdataprogram | tee fifo | stream1 ... &
cat fifo | stream2 ...
Don't forget to rm fifo when done with it.
--
Regards, pd@x.co.uk IXI Limited
Paul Davey pd@ixi.uucp 62-74 Burleigh St.
...!uunet!ixi!pd Cambridge U.K.
"These are interesting times" +44 223 462 131 CB1 1OJ
USA: 1 800 XDESK 57
ruba@molbio.ethz.ch (Rudolf Baumann) (06/08/91)
pete@othello.dartmouth.edu (Pete Schmitt) writes: >Is there a tee like program that will pipe down to another program? I am using tpipe from David Rosen which once appeared in comp.sources.unix: %Newsgroups: comp.sources.unix %Subject: v22i011: A "tee" that feeds into pipes. %Message-ID: <2484@papaya.bbn.com> %Date: 3 May 90 20:43:46 GMT %Approved: rsalz@uunet.UU.NET % %Submitted-by: David B Rosen <rosen@bucasb.bu.edu> %Posting-number: Volume 22, Issue 11 %Archive-name: tpipe % %tpipe is a simple utility program that can be used to split a unix %pipeline into two pipelines. That is, the output of one pipeline can %be replicated and supplied as the input to two other pipelines %executing simultaneously. % %For example % cmd1 <infile | tpipe "cmd2 | cmd3 >outfile" | cmd4 %will look like this diagramatically: % % --> cmd2 --> cmd3 --> outfile % / % infile --> cmd1 -< % \\ % --> cmd4 --> (standard output) That is probably what you are looking for. Ruedi -- Rudolf E. Baumann ruba@molbio.ethz.ch Institut fuer Molekularbiologie & Biophysik MOLEKULA@CZHETH5A.bitnet ETH Hoenggerberg (HPM G6) Tel. ++41 1 377 33 97 CH-8093 Zuerich/Switzerland Fax ++41 1 371 48 73
renkel@motcid.UUCP (Will Renkel) (06/10/91)
In article <PD.91Jun7133525@powys.x.co.uk>, pd@pd@x.co.uk (Paul Davey) writes: > > >>>>> On 6 Jun 91 09:39:39 GMT, pete@othello.dartmouth.edu (Pete Schmitt) said: > > Pete> Is there a tee like program that will pipe down to another program? > > You can get the effect of this on some machines by using tee and a > named pipe or fifo file. (This is not a general solution.) > > to pipe the output from lotsofdataprogram to stream1 and stream2, > > > mknod fifo p > lotsofdataprogram | tee fifo | stream1 ... & > cat fifo | stream2 ... > > > Don't forget to rm fifo when done with it. > > -- > Regards, pd@x.co.uk IXI Limited > Paul Davey pd@ixi.uucp 62-74 Burleigh St. > ...!uunet!ixi!pd Cambridge U.K. > "These are interesting times" +44 223 462 131 CB1 1OJ > USA: 1 800 XDESK 57 Got this code while working at ATT Bell Labs I call it "branch" and its use is like the following echo HI | branch 'grep HI | grep HI >stream1' | while read p1 do echo $p1 done | tee stream2 --------- CUT HERE ----------------. #include <stdio.h> /* Similiar to the shell command "tee", but the standard input * is copied into two different pipelines at the same time *J. Leth, IH 6E-318 x6613. */ #define STRLEN 255 #define errexit(x,arg) fprintf(stderr, x, arg); exit(1) main(argc, argv) int argc; char *argv[]; { char *command; int fildes[2]; /* file descriptors for created pipe * fildes[0] is reader, fildes[1] is writer */ if (argc != 2) { printf("\n\nUsage:\tbranch <command>\n"); printf("Copies standard input to standard output, and\n"); printf("at the same time copies it to the given command.\n"); printf("The Command may itself be a pipeline (be careful\n"); printf("to enclose it in quotes).\n"); printf("example - cat abc | branch \"grep tss >temp1\" | grep qqq\n"); errexit("\n\n\n",1); } command = argv[1]; if (pipe(fildes) == -1) { errexit("branch: can't get new pipe\n",0); } switch (fork()) { case -1: errexit("branch: can't fork\n",0); case 0: /* brancher process -- Execute command with standard input * taken from pipe from forker process. */ close(fildes[1]); /* close writer */ /* Duplicate pipe reader as standard input */ close(0); dup(fildes[0]); execl("/bin/sh", "/bin/sh", "-c", command, 0); default: { /* Forker process */ int c; FILE *pipewrt; close(fildes[0]); /* close reader */ pipewrt = fdopen(fildes[1], "w"); setbuf(pipewrt, NULL); while(!feof(stdin) && !ferror(stdin)) { putchar(c = getchar()); putc(c, pipewrt); } fclose(pipewrt); fclose(stdin); exit(0); } } }