gawk: Tee Program
1
1 11.2.5 Duplicating Output into Multiple Files
1 ---------------------------------------------
1
1 The 'tee' program is known as a "pipe fitting." 'tee' copies its
1 standard input to its standard output and also duplicates it to the
1 files named on the command line. Its usage is as follows:
1
1 'tee' ['-a'] FILE ...
1
1 The '-a' option tells 'tee' to append to the named files, instead of
1 truncating them and starting over.
1
1 The 'BEGIN' rule first makes a copy of all the command-line arguments
1 into an array named 'copy'. 'ARGV[0]' is not needed, so it is not
1 copied. 'tee' cannot use 'ARGV' directly, because 'awk' attempts to
1 process each file name in 'ARGV' as input data.
1
1 If the first argument is '-a', then the flag variable 'append' is set
1 to true, and both 'ARGV[1]' and 'copy[1]' are deleted. If 'ARGC' is
1 less than two, then no file names were supplied and 'tee' prints a usage
1 message and exits. Finally, 'awk' is forced to read the standard input
1 by setting 'ARGV[1]' to '"-"' and 'ARGC' to two:
1
1 # tee.awk --- tee in awk
1 #
1 # Copy standard input to all named output files.
1 # Append content if -a option is supplied.
1 #
1 BEGIN {
1 for (i = 1; i < ARGC; i++)
1 copy[i] = ARGV[i]
1
1 if (ARGV[1] == "-a") {
1 append = 1
1 delete ARGV[1]
1 delete copy[1]
1 ARGC--
1 }
1 if (ARGC < 2) {
1 print "usage: tee [-a] file ..." > "/dev/stderr"
1 exit 1
1 }
1 ARGV[1] = "-"
1 ARGC = 2
1 }
1
1 The following single rule does all the work. Because there is no
1 pattern, it is executed for each line of input. The body of the rule
1 simply prints the line into each file on the command line, and then to
1 the standard output:
1
1 {
1 # moving the if outside the loop makes it run faster
1 if (append)
1 for (i in copy)
1 print >> copy[i]
1 else
1 for (i in copy)
1 print > copy[i]
1 print
1 }
1
1 It is also possible to write the loop this way:
1
1 for (i in copy)
1 if (append)
1 print >> copy[i]
1 else
1 print > copy[i]
1
1 This is more concise, but it is also less efficient. The 'if' is tested
1 for each record and for each output file. By duplicating the loop body,
1 the 'if' is only tested once for each input record. If there are N
1 input records and M output files, the first method only executes N 'if'
1 statements, while the second executes N'*'M 'if' statements.
1
1 Finally, the 'END' rule cleans up by closing all the output files:
1
1 END {
1 for (i in copy)
1 close(copy[i])
1 }
1