8

I want to print same lines to 2 different files. What I am doing right now is:

print ID[i]" "Value[i]" "TS1[i]" "TS2[i] > "file1.txt";
print ID[i]" "Value[i]" "TS1[i]" "TS2[i] > "file2.txt";

Can I write a single command to redirect it to two different files ?

EDIT

I don't want to print my whole command output to the multiple files, I want to write some of records based on some condition into multiple files,I am printing this within awk script so I need an efficient way to do it.

2
  • It's not clear what you want. You say that they are same lines, but then you say that they are not whole lines.
    – LatinSuD
    Jun 24, 2014 at 9:59
  • Is it that you want to use a variable? MYLINE=ID[i]" "...; print MYLINE >> file1.txt; print MYLINE >> file2.txt ?
    – LatinSuD
    Jun 24, 2014 at 10:02

4 Answers 4

11

You can not do it with awk.

Using tee, you can do something like this:

$ awk '{print ID[i]" "Value[i]" "TS1[i]" "TS2[i]}' file | tee out1 out2

Using tee -a if you want to append instead of override existed files.

If you don't want to print the whole output, you can try:

awk '
    BEGIN {outfile["a.txt"];outfile["b.txt"]}
    { for (file in outfile) { print > file } }' file
3
  • Thanks for you answer but I dont wanna print my whole command output to multiple files.
    – Aashu
    Jun 24, 2014 at 9:49
  • 2
    You can do the pipe inside awk. command = "tee file1.txt file2.txt"; print message | command;
    – Matt
    Jun 24, 2014 at 11:39
  • @mtm: Yes, I want to add it but Stéphane Chazelas had answerd.
    – cuonglm
    Jun 24, 2014 at 11:42
11

Within awk, instead of redirecting to a file with print "text" > "file", you can redirect to a command using:

print "something" | "tee file1.txt file2.txt"

The first time you use that |, awk spawns the command, and the next time it reuses the same command, so it doesn't start a new tee each time you do that and doesn't overwrite the files (you need to call close("tee file1.txt file2.txt") if you do want awk to start a new command the next time). However, if you do both > "file1.txt" and | "tee file1.txt..." there will be a conflict.

You may then want to use >> "file1.txt" and | "tee -a file1.txt..." instead.

However, I'd still go with @cuonglm's for approach or use an awk function as that would be cleaner and more efficient.

3
5

A user defined function might make your code cleaner and cause less duplication, if that's what the concern is.

function print_to_files( message, file_a, file_b ) {
   print message > file_a;
   print message > file_b;
}

message = sprintf( "%s %s %s %s", ID[i], Value[i], TS1[i], TS2[i] )
print_to_files( message , "filea", "fileb" );'

Or hard code the files if that's all you need.

function print_to_files( message ) {
   print message > "/path/to/filea";
   print message > "/path/to/fileb";
}

message = sprintf( "%s %s %s %s", ID[i], Value[i], TS1[i], TS2[i] )
print_to_files( message );'
4

You can do this with sed - but without a clearer idea of your input, I don't know how to demonstrate it specifically. Still, here is a generic example:

seq 10 | sed -ne '/1/w ./onesfile.txt' -e '/3/w threesfile.txt'

That writes only the lines containing a 1 to the onesfile.txt and otherwise for 3 - everything else is deleted. This is a very basic example of how this might work, but if you could provide sample input I might do a little better.

Once sed opens a file for writing it remains open until the process is completed - it does not continuously truncate its own writes - the file descriptors are retained for the life of the process.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .