.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "File::Tee 3pm" .TH File::Tee 3pm "2022-10-13" "perl v5.34.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" File::Tee \- replicate data sent to a Perl stream .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use File::Tee qw(tee); \& \& # simple usage: \& tee(STDOUT, \*(Aq>\*(Aq, \*(Aqstdout.txt\*(Aq); \& \& print "hello world\en"; \& system "ls"; \& \& # advanced usage: \& my $pid = tee STDERR, { prefix => "err[$$]: ", reopen => \*(Aqmy.log\*(Aq}; \& \& print STDERR "foo\en"; \& system("cat /bad/path"); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module is able to replicate data written to a Perl stream into another streams. It is the Perl equivalent of the shell utility \&\fBtee\fR\|(1). .PP It is implemented around \f(CW\*(C`fork\*(C'\fR, creating a new process for every tee'ed stream. That way, there are no problems handling the output generated by external programs run with system or by \s-1XS\s0 modules that don't go through perlio. .SS "\s-1API\s0" .IX Subsection "API" The following function can be imported from this module: .ie n .IP "tee $fh, $target, ..." 4 .el .IP "tee \f(CW$fh\fR, \f(CW$target\fR, ..." 4 .IX Item "tee $fh, $target, ..." redirects a copy of the data written to \f(CW$fh\fR to one or several files or streams. .Sp \&\f(CW\*(C`$target, ...\*(C'\fR is a list of target streams specifications that can be: .RS 4 .IP "\(bu" 4 file names with optional mode specifications: .Sp .Vb 2 \& tee STDOUT, \*(Aq>> /tmp/out\*(Aq, \*(Aq>> /tmp/out2\*(Aq; \& tee STDOUT, \*(Aq>>\*(Aq, \*(Aq/tmp/out\*(Aq, \*(Aq/tmp/out2\*(Aq; .Ve .Sp If the mode specification is a separate argument, it will affect all the file names following and not just the nearest one. .Sp If mode \f(CW\*(C`|\-\*(C'\fR is used as a separate argument, the rest of the arguments are slurped as arguments for the pipe command: .Sp .Vb 2 \& tee STDERR, \*(Aq|\-\*(Aq, \*(Aqgrep\*(Aq, \*(Aq\-i\*(Aq, \*(Aqerror\*(Aq; \& tee STDERR, \*(Aq| grep \-i error\*(Aq; # equivalent .Ve .Sp Valid modes are \f(CW\*(C`>\*(C'\fR, \f(CW\*(C`>>\*(C'\fR, \f(CW\*(C`>&\*(C'\fR, \f(CW\*(C`>>&\*(C'\fR and \f(CW\*(C`|\-\*(C'\fR. The default mode is \f(CW\*(C`>>\*(C'\fR. .Sp File handles can also be used as targets: .Sp .Vb 3 \& open my $target1, \*(Aq>>\*(Aq, \*(Aq/foo/bar\*(Aq; \& ... \& tee STDOUT, $target1, $target2, ...; .Ve .Sp Finally, code references can also be used as targets. The callback will be invoked for every line written to the tee'ed stream with the data in \f(CW$_\fR. It has to return a true value on success or false if some error happens. Also, note that the callback will be called from a different process. .IP "\(bu" 4 hash references describing the targets .Sp For instance: .Sp .Vb 1 \& tee STDOUT, { mode => \*(Aq>>\*(Aq, open => \*(Aq/tmp/foo\*(Aq, lock => 1}; .Ve .Sp will copy the data sent to \s-1STDOUT\s0 to \f(CW\*(C`/tmp/foo\*(C'\fR. .Sp The attributes that can be included inside the hash are: .RS 4 .ie n .IP "open => $file_name" 4 .el .IP "open => \f(CW$file_name\fR" 4 .IX Item "open => $file_name" .PD 0 .ie n .IP "reopen => $file_name" 4 .el .IP "reopen => \f(CW$file_name\fR" 4 .IX Item "reopen => $file_name" .PD sets the target file or stream. It can contain a mode specification and also be an array. For instance: .Sp .Vb 3 \& tee STDOUT, { open => \*(Aq>> /tmp/out\*(Aq }; \& tee STDOUT, { reopen => [\*(Aq>>\*(Aq, \*(Aq/tmp/out2\*(Aq] }; \& tee STDOUT, { open => \*(Aq| grep foo > /tmp/out\*(Aq }; .Ve .Sp If \f(CW\*(C`reopen\*(C'\fR is used, the file or stream is reopen for every write operation. The mode will be forced to append after the first write. .ie n .IP "mode => $mode" 4 .el .IP "mode => \f(CW$mode\fR" 4 .IX Item "mode => $mode" Alternative way to specify the mode to open the target file or stream .ie n .IP "lock => $bool" 4 .el .IP "lock => \f(CW$bool\fR" 4 .IX Item "lock => $bool" When true, an exclusive lock is obtained on the target file before writing to it. .ie n .IP "prefix => $txt" 4 .el .IP "prefix => \f(CW$txt\fR" 4 .IX Item "prefix => $txt" Some text to be prepended to every line sent to the target file. .Sp For instance: .Sp .Vb 2 \& tee STDOUT, { prefix => \*(AqOUT: \*(Aq, lock => 1, mode => \*(Aq>>\*(Aq, open => \*(Aq/tmp/out.txt\*(Aq }; \& tee STDERR, { prefix => \*(AqERR: \*(Aq, lock => 1, mode => \*(Aq>>\*(Aq, open => \*(Aq/tmp/out.txt\*(Aq }; .Ve .IP "preprocess => sub { ... }" 4 .IX Item "preprocess => sub { ... }" A callback function that can modify the data before it gets sent to the target file. .Sp For instance: .Sp .Vb 12 \& sub hexdump { \& my $data = shift; \& my @out; \& while ($data =~ /(.{1,32})/smg) { \& my $line=$1; \& my @c= (( map { sprintf "%02x",$_ } unpack(\*(AqC*\*(Aq, $line)), \& ((" ") x 32))[0..31]; \& $line=~s/(.)/ my $c=$1; unpack("c",$c)>=32 ? $c : \*(Aq.\*(Aq /egms; \& push @out, join(" ", @c, \*(Aq|\*(Aq, $line), "\en"; \& } \& join(\*(Aq\*(Aq, @out); \& } \& \& tee BINFH, { preprocess => \e&hexdump, open => \*(Aq/tmp/hexout\*(Aq}; .Ve .ie n .IP "autoflush => $bool" 4 .el .IP "autoflush => \f(CW$bool\fR" 4 .IX Item "autoflush => $bool" Sets autoflush mode for the target streams. Default is on. .ie n .IP "ignore_errors => $bool" 4 .el .IP "ignore_errors => \f(CW$bool\fR" 4 .IX Item "ignore_errors => $bool" By default, when writing to the targets, any error will close the tee'ed handle. This option allows one to change that behaviour. .IP "process => sub { ... }" 4 .IX Item "process => sub { ... }" the callback will be called for every line read (see using code references as targets discussion above). This option can not be used at the same time as most other options (open, reopen, lock, autoflush, etc.). .IP "begin => sub { ... }" 4 .IX Item "begin => sub { ... }" .PD 0 .IP "end => sub { ... }" 4 .IX Item "end => sub { ... }" .PD Those functions are called on the forked process before the first write and when closing the handle respectively. .Sp For instance: .Sp .Vb 3 \& my @capture; \& tee STDERR, { process => sub { push @capture, $_ }, \& end => sub { send_mail \*(Aqfoo@bar.com\*(Aq, \*(Aqstderr capture\*(Aq, "@capture" } }; .Ve .RE .RS 4 .RE .RE .RS 4 .Sp The function returns the \s-1PID\s0 for the newly created process. .Sp Inside the \f(CW\*(C`tee\*(C'\fR pipe process created, data is read honouring the input record separator \f(CW$/\fR. .Sp You could also want to set the tee'ed stream in autoflush mode: .Sp .Vb 1 \& open $fh, ...; \& \& my $oldsel = select $fh; \& $| = 1; \& select $fh; \& \& tee $fh, "> /tmp/log"; .Ve .RE .SH "BUGS" .IX Header "BUGS" Does not work on Windows (patches welcome). .PP Send bug reports by email or via the \s-1CPAN RT\s0 web . .SH "SEE ALSO" .IX Header "SEE ALSO" IO::Capture .PP IO::Tee is a similar module implemented around tied file handles. Tee allows one to launch external processes capturing their output to some files. IO::CaptureOutput allows one to capture the output generated from a child process or a subroutine. .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (C) 2007, 2008, 2010, 2011 by Salvador FandiƱo (sfandino@yahoo.com) .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.