Not all systems support the classictee
program for splitting output pipes to multiple destinations. This command sends the output from someprog to/tmp/output
and to the mail pipe beyond.
% someprog | tee /tmp/output | Mail -s 'check this' user@host.org
This program helps not only users who aren't on Unix systems and don't
have a regular tee
. It also helps those who are, because it offers
features not found on other version of tee.
The four flag arguments are-i
to ignore interrupts,-a
to append to output files,-u
for unbuffered output, and-n
to omit copying the output on to standard out.
Veamos algunas ejecuciones:
lhp@nereida:~/Lgroovy/files$ echo 'hola LHP' |./tctee.groovy file1 file2 hola LHP lhp@nereida:~/Lgroovy/files$ cat file1 file2 hola LHP hola LHP lhp@nereida:~/Lgroovy/files$ echo 'hola mundo' |./tctee.groovy -n '| cat -n' file2 1 hola mundo lhp@nereida:~/Lgroovy/files$ cat file2 hola mundo lhp@nereida:~/Lgroovy/files$ echo 'hola mundo' |./tctee.groovy -n '| cat -n' '>>file2' 1 hola mundo lhp@nereida:~/Lgroovy/files$ cat file2 hola mundo hola mundo
generaciondecodigos@nereida:~/src/groovy/files$ cat -n tctee.groovy 1 #!/usr/bin/env groovy 2 class MultiStream { 3 private targets 4 private ignoreErrors 5 MultiStream(List targets, ignore) { 6 this.targets = targets 7 ignoreErrors = ignore 8 } 9 def println(String content) { 10 targets.each{ 11 try { 12 it?.write(content.bytes) 13 } catch (Exception ex) { 14 if (!ignoreErrors) throw ex 15 targets -= it 16 it?.close() 17 } 18 } 19 } 20 def close() { targets.each{ it?.close() } } 21 } 22 23 class TeeTarget { 24 private filename 25 private stream 26 private p 27 28 TeeTarget(String name, append, buffered, ignore) { 29 if (name.startsWith('>>')) { 30 createFileStream(name[2..-1],true,buffered,ignore) 31 } else if (name.startsWith('|')) { 32 createProcessReader(name[1..-1]) 33 } else { 34 createFileStream(name,append,buffered,ignore) 35 } 36 } 37 38 TeeTarget(OutputStream stream) { this.stream = stream } 39 40 def write(bytes) { stream?.write(bytes) } 41 def close() { stream?.close() } 42 43 private createFileStream(name, append, buffered, ignore) { 44 filename = name 45 def fos 46 try { 47 fos = new FileOutputStream(name, append) 48 } catch (Exception ex) { 49 if (ignore) return 50 } 51 if (!buffered) stream = fos 52 else stream = new BufferedOutputStream(fos) 53 } 54 private createWriter(os) {new PrintWriter(new BufferedOutputStream(os))} 55 private createReader(is) {new BufferedReader(new InputStreamReader(is))} 56 private createPiperThread(br, pw) { 57 Thread.start{ 58 def next 59 while((next = br.readLine())!=null) { 60 pw.println(next) 61 } 62 pw.flush(); pw.close() 63 } 64 } 65 private createProcessReader(name) { 66 def readFromStream = new PipedInputStream() 67 def r1 = createReader(readFromStream) 68 stream = new BufferedOutputStream(new PipedOutputStream(readFromStream)) 69 p = Runtime.runtime.exec(name) 70 def w1 = createWriter(p.outputStream) 71 createPiperThread(r1, w1) 72 def w2 = createWriter(System.out) 73 def r2 = createReader(p.inputStream) 74 createPiperThread(r2, w2) 75 } 76 } 77 78 targets = [] 79 append = false; ignore = false; includeStdout = true; buffer = true 80 (0..<args.size()).each{ 81 arg = args[it] 82 if (arg.startsWith('-')) { 83 switch (arg) { 84 case '-a': append = true; break 85 case '-i': ignore = true; break 86 case '-n': includeStdout = false; break 87 case '-u': buffer = false; break 88 default: 89 println "usage: tee [-ainu] [filenames] ..." 90 System.exit(1) 91 } 92 } else targets += arg 93 } 94 targets = targets.collect{ new TeeTarget(it, append, buffer, ignore) } 95 if (includeStdout) targets += new TeeTarget(System.out) 96 def tee = new MultiStream(targets, ignore) 97 def stdin = new BufferedReader(new InputStreamReader(System.in)) 98 99 stdin.eachLine { line -> 100 tee.println("$line\n") 101 } 102 tee.close()
Casiano Rodríguez León