Search code examples
bashhttp-redirectawkstdoutstderr

Redirect to a file STDOUT first and then STDERR


I have a gawk code like this.

#!/usr/bin/gawk -f

1 {
    for (i=0;i<5;i++){
        print $0
        print $0, i > "/dev/stderr"
    }
}

I want to redirect to a file tmp, first the stdout and then the stderr. I tried this:

gawk -f Documents/gawk_script.awk ./file &> tmp

But this call append to the file first stderr. I don't want to divide them into two files, so I'm asking if there's a way to do that.

In ./file there's such a line:

hello
hello
howareyou
well
well

while in tmp file

hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
howareyou
howareyou
howareyou
howareyou
howareyou
well
well
well
well
well
well
well
well
well
well
well
hello 0
hello 1
hello 2
hello 3
hello 4 
hello 0
hello 1
hello 2
hello 3
hello 4
howareyou 0
howareyou 1
howareyou 2
howareyou 3
howareyou 4
well 0
well 1
well 2
well 3
well 4
well 0
well 1
well 2
well 3
well 4

Solution

  • There is no good way* to tell awk or the shell that it must buffer stderr until the tool finishes executing. Keep it simple and just do this:

    awk -f script.awk file > out 2>tmp; cat tmp >> out && rm -f tmp
    

    Otherwise you could buffer stderr yourself and print at the end (but this will only work for stderr messages you are manually printing, not messages gawk is generating itself):

    {
        for (i=0;i<5;i++){
            print $0
            errs = errs $0 OFS i ORS
        }
    }
    END {
        printf "%s", errs > "/dev/stderr"
    }
    

    and then call as:

    awk -f script.awk file > out 2>&1
    

    Of course you don't actually need to use stderr at all if that's all you're doing with it, just print to stdout.

    *There may be some arcane incantation you can use to make this happen if the planets align a certain way and/or you have certain tools or a certain shell but just keep it simple as shown above.