Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Mixing and multiple redirection of stderr/stdout



On May 18,  3:25am, Michael Lehn wrote:
}
} Some script produces output on stdout and stderr, now I want
} 
} (1) redirect the sync-mix of stdout and stderr to some file file_mix
} (2) redirect stdout to file_out
} (3) redirect stderr to file_err
} 
} However, I even fail when I try to achieve only (1) and (3) via
} 
} 	./script > file_mix 2>&1 2>file_err

This will only work if you have setopt MULT_IOS in effect, but if it
is, then the above should be correct.  Let's set up a little test
case so it's easier to see:

torch% [[ -o multios ]] && echo yes
yes

OK, we have multios.  Next we need a script that produces output on
both streams.

torch% function script { print STDOUT; print -u2 STDERR }

Then some "files" we can redirect into that will tell us what stream
the file is actually seeing.

torch% alias -g file_err='>(sed s/^/file_err:/)'
torch% alias -g file_out='>(sed s/^/file_out:/)'
torch% alias -g file_mix='>(sed s/^/file_mix:/)'

And now your (1) and (3) test:

torch% script >file_mix 2>&1 2>file_err          
file_mix:STDOUT
file_mix:STDERR
file_err:STDERR

The order of the redirections is important.  If we just throw >file_out
onto the end:

torch% script >file_mix 2>&1 2>file_err >file_out
file_mix:STDERR
file_out:STDOUT
file_err:STDERR

Here, 1 (stdout) is pointed at file_mix and then descriptor 2 (stderr)
is made a duplicate of descriptor 1; but then 1 is redirected again to
file_out leaving only 2 pointing at file_mix.  In effect "2>&1" turns
off the multio state for 1, and until *after* another redirection
like ">file_out", descriptor 1 is not again eligible for splitting
into more than one stream.

The non-obvious trick here is that you can re-enable the multio state
by redirecting a descriptor TO ITSELF:

torch% script >file_mix 2>&1 2>file_err 1>&1 >file_out
file_mix:STDERR
file_mix:STDOUT
file_err:STDERR
file_out:STDOUT

And there you have what you want.  However, it needn't be that ugly.

The next trick is that zsh has a shorthand operator ">&" (no numbers
around it) that means "redirect both stdout and stderr at the same
time".  This is done without destroying one of the original streams
in the way that happens when you use "2>&1".  So:

torch% script >&file_mix >file_out 2>file_err
file_out:STDOUT
file_mix:STDOUT
file_mix:STDERR
file_err:STDERR

And there you are.

-- 



Messages sorted by: Reverse Date, Date, Thread, Author