zsh: STDERR to a variable?

zsh: STDERR to a variable?

am 27.01.2008 21:23:13 von kj

I know that one can redirect a command's STDERR output to a file:

% foo bar baz 2>capture_errors

Is there a way (in zsh) to capture the errors in a shell or local
variable instead? And is it possible to have this output *appended*
to the contents of a shell or local variable?

Thanks!

Kynn

--
NOTE: In my address everything before the first period is backwards;
and the last period, and everything after it, should be discarded.

Re: zsh: STDERR to a variable?

am 27.01.2008 21:49:33 von Stephane CHAZELAS

On Sun, 27 Jan 2008 20:23:13 +0000 (UTC), kj wrote:
>
>
>
> I know that one can redirect a command's STDERR output to a file:
>
> % foo bar baz 2>capture_errors
>
> Is there a way (in zsh) to capture the errors in a shell or local
> variable instead? And is it possible to have this output *appended*
> to the contents of a shell or local variable?
[...]

{ errors+=$(foo bar baz 2>&1 >&3 3>&-) } >&3

You can even make it standard sh:

{ errors=$errors$(foo bar baz 2>&1 >&3 3>&-); } >&3

(BTW, what different do you make between a shell and local
variable?)

--
Stephane

Re: zsh: STDERR to a variable?

am 28.01.2008 01:00:44 von Alexander Gilman Carver

On Sun, 27 Jan 2008, Stephane Chazelas (stephane_chazelas@yahoo.fr) wrote...

> On Sun, 27 Jan 2008 20:23:13 +0000 (UTC), kj wrote:
>>
>>
>>
>> I know that one can redirect a command's STDERR output to a file:
>>
>> % foo bar baz 2>capture_errors
>>
>> Is there a way (in zsh) to capture the errors in a shell or local
>> variable instead? And is it possible to have this output *appended*
>> to the contents of a shell or local variable?
> [...]
>
> { errors+=$(foo bar baz 2>&1 >&3 3>&-) } >&3
>
> You can even make it standard sh:
>
> { errors=$errors$(foo bar baz 2>&1 >&3 3>&-); } >&3

WHat form of redirection does 3>&- represent? You send the standard output
to file descriptor 3 to where (&-)? If I follow your logic, standard error
goes to where standard input is going, then standard input is going to
where file descriptor is going and file descriptor 3 is going to???

Georg
> >
(BTW, what different do you make between a shell and local > variable?)
>
> --
> Stephane
>

Re: zsh: STDERR to a variable?

am 28.01.2008 01:58:08 von Bill Marcum

On 2008-01-28, George wrote:
>
>
>
> WHat form of redirection does 3>&- represent? You send the standard output
> to file descriptor 3 to where (&-)? If I follow your logic, standard error
> goes to where standard input is going, then standard input is going to
> where file descriptor is going and file descriptor 3 is going to???
>
>&- means close the file descriptor.

Re: zsh: STDERR to a variable?

am 28.01.2008 09:35:58 von Stephane CHAZELAS

On Mon, 28 Jan 2008 00:00:44 +0000, George wrote:
[...]
>>> Is there a way (in zsh) to capture the errors in a shell or local
>>> variable instead? And is it possible to have this output *appended*
>>> to the contents of a shell or local variable?
>> [...]
>>
>> { errors+=$(foo bar baz 2>&1 >&3 3>&-) } >&3
[...]
> WHat form of redirection does 3>&- represent? You send the standard output
> to file descriptor 3 to where (&-)?

To nothing, foo won't write anything to its fd 3 unless it opens
it by itself, so there's no point in leaving it open, so we
close it. Leaving it open would probably not harm, but is less
tidy.

> If I follow your logic, standard error
> goes to where standard input is going, then standard input is going to
> where file descriptor is going and file descriptor 3 is going to???
[...]

Yes, except that it's "standard *output*", not *input*.

--
Stephane

Re: zsh: STDERR to a variable?

am 28.01.2008 13:33:24 von kj

In <479cee5c$0$907$ba4acef3@news.orange.fr> Stephane Chazelas writes:

>On Sun, 27 Jan 2008 20:23:13 +0000 (UTC), kj wrote:
>>
>>
>>
>> I know that one can redirect a command's STDERR output to a file:
>>
>> % foo bar baz 2>capture_errors
>>
>> Is there a way (in zsh) to capture the errors in a shell or local
>> variable instead? And is it possible to have this output *appended*
>> to the contents of a shell or local variable?
>[...]

>{ errors+=$(foo bar baz 2>&1 >&3 3>&-) } >&3

>You can even make it standard sh:

>{ errors=$errors$(foo bar baz 2>&1 >&3 3>&-); } >&3

A command substitution! Of course. That's another
one I should have come up with by myself.

Looking at this solution one thing that is clear is that it would
be difficult (if not impossible) to extend it to the case where
one wanted to capture both stderr *and* stdout. Maybe there's a
way, but these shell redirection acrobatics always take me quite
a while to figure out... It'll be the puzzle of the day...

>(BTW, what different do you make between a shell and local
>variable?)

I don't, actually, but *if* by any chance there had been any
difference (unbeknownst to me) between them I wanted to know about
it, because the immediate need I have for this maneuver involves
the use of a local variable as the recipient of the error stream.

Thanks again!

kynn

--
NOTE: In my address everything before the first period is backwards;
and the last period, and everything after it, should be discarded.

Re: zsh: STDERR to a variable?

am 28.01.2008 14:21:13 von Stephane CHAZELAS

On Mon, 28 Jan 2008 12:33:24 +0000 (UTC), kj wrote:
[...]
>>{ errors=$errors$(foo bar baz 2>&1 >&3 3>&-); } >&3
>
> A command substitution! Of course. That's another
> one I should have come up with by myself.
>
> Looking at this solution one thing that is clear is that it would
> be difficult (if not impossible) to extend it to the case where
> one wanted to capture both stderr *and* stdout. Maybe there's a
> way, but these shell redirection acrobatics always take me quite
> a while to figure out... It'll be the puzzle of the day...
[...]

If you want both stdout and stderr, it's simpler:

out_and_err=$(foo bar baz 2>&1)

--
Stephane

Re: zsh: STDERR to a variable?

am 29.01.2008 03:06:17 von Barry Margolin

In article <479dd6c9$0$890$ba4acef3@news.orange.fr>,
Stephane Chazelas wrote:

> On Mon, 28 Jan 2008 12:33:24 +0000 (UTC), kj wrote:
> [...]
> >>{ errors=$errors$(foo bar baz 2>&1 >&3 3>&-); } >&3
> >
> > A command substitution! Of course. That's another
> > one I should have come up with by myself.
> >
> > Looking at this solution one thing that is clear is that it would
> > be difficult (if not impossible) to extend it to the case where
> > one wanted to capture both stderr *and* stdout. Maybe there's a
> > way, but these shell redirection acrobatics always take me quite
> > a while to figure out... It'll be the puzzle of the day...
> [...]
>
> If you want both stdout and stderr, it's simpler:
>
> out_and_err=$(foo bar baz 2>&1)

But if you want them in separate variables, you need to write one of
them to a temp file or pipe.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***

Re: zsh: STDERR to a variable?

am 29.01.2008 09:40:06 von Stephane CHAZELAS

On Mon, 28 Jan 2008 21:06:17 -0500, Barry Margolin wrote:
[...]
>> If you want both stdout and stderr, it's simpler:
>>
>> out_and_err=$(foo bar baz 2>&1)
>
> But if you want them in separate variables, you need to write one of
> them to a temp file or pipe.

(I suppose you meant named pipe as stdout inside $(...) is a
pipe).

Not necessarily, you could do things like

err= out= NL='
'
eval "$(
{
{
foo bar baz 3>&- | sed "
s/'/'\''/g
s/.*/out=\$out'&'\$NL/
" >&3
} 2>&1 | sed "
s/'/'\''/g
s/.*/err=\$err'&'\$NL/
"
} 3>&1
)"

Though I suspect there might be problems with regards to how sed
writes to its stdout by buffers (which could mean improper
interleaving of the two seds output).

In which case, you could do:

eval "out=$(
{
err=$(
{
foo bat baz 2>&4 4>&- | sed "s/'/'\''/g;1s/^/'/;\$s/\$/'/"
} 4>&1 >&3 3>&- | sed "s/'/'\''/g;1s/^/'/;\$s/\$/'/"
)
printf ' err=%s\n' "$err"
} 3>&1
)"

--
Stephane

Re: zsh: STDERR to a variable?

am 29.01.2008 13:10:14 von kj

In <479dd6c9$0$890$ba4acef3@news.orange.fr> Stephane Chazelas writes:

>On Mon, 28 Jan 2008 12:33:24 +0000 (UTC), kj wrote:
>[...]
>>>{ errors=$errors$(foo bar baz 2>&1 >&3 3>&-); } >&3
>>
>> A command substitution! Of course. That's another
>> one I should have come up with by myself.
>>
>> Looking at this solution one thing that is clear is that it would
>> be difficult (if not impossible) to extend it to the case where
>> one wanted to capture both stderr *and* stdout. Maybe there's a
>> way, but these shell redirection acrobatics always take me quite
>> a while to figure out... It'll be the puzzle of the day...
>[...]

>If you want both stdout and stderr, it's simpler:

>out_and_err=$(foo bar baz 2>&1)

Sorry, I was not clear: I meant capturing both stderr and stdout
to separate variables.

kynn
--
NOTE: In my address everything before the first period is backwards;
and the last period, and everything after it, should be discarded.

Re: zsh: STDERR to a variable?

am 29.01.2008 13:24:19 von kj

In <479ee666$0$879$ba4acef3@news.orange.fr> Stephane Chazelas writes:

>On Mon, 28 Jan 2008 21:06:17 -0500, Barry Margolin wrote:
>[...]
>>> If you want both stdout and stderr, it's simpler:
>>>
>>> out_and_err=$(foo bar baz 2>&1)
>>
>> But if you want them in separate variables, you need to write one of
>> them to a temp file or pipe.

>(I suppose you meant named pipe as stdout inside $(...) is a
>pipe).

>Not necessarily, you could do things like

>err= out= NL='
>'
>eval "$(
> {
> {
> foo bar baz 3>&- | sed "
> s/'/'\''/g
> s/.*/out=\$out'&'\$NL/
> " >&3
> } 2>&1 | sed "
> s/'/'\''/g
> s/.*/err=\$err'&'\$NL/
> "
> } 3>&1
>)"

>Though I suspect there might be problems with regards to how sed
>writes to its stdout by buffers (which could mean improper
>interleaving of the two seds output).

>In which case, you could do:

>eval "out=$(
> {
> err=$(
> {
> foo bat baz 2>&4 4>&- | sed "s/'/'\''/g;1s/^/'/;\$s/\$/'/"
> } 4>&1 >&3 3>&- | sed "s/'/'\''/g;1s/^/'/;\$s/\$/'/"
> )
> printf ' err=%s\n' "$err"
> } 3>&1
>)"


!!!

Since I learned to use Perl many years ago I completely forgot the
little sed I ever knew... But I'll brush up on it just to understand
the maneuvers above!

Thanks,

kynn

--
NOTE: In my address everything before the first period is backwards;
and the last period, and everything after it, should be discarded.

Re: zsh: STDERR to a variable?

am 29.01.2008 16:38:31 von pgas

Stephane Chazelas wrote:
> On Mon, 28 Jan 2008 21:06:17 -0500, Barry Margolin wrote:
> [...]
>>> If you want both stdout and stderr, it's simpler:
>>>
>>> out_and_err=$(foo bar baz 2>&1)
>>
>> But if you want them in separate variables, you need to write one of
>> them to a temp file or pipe.
>
> (I suppose you meant named pipe as stdout inside $(...) is a
> pipe).
>

Another possible hack (bash and ksh required for the $'\n'):

result=$( { stdout=$(cmd) ; } 2>&1; echo "this line is the separator"; printf "%s" "$stdout")
var_out=${result#*this line is the separator$'\n'}
var_err=${result%$'\n'this line is the separator*}

Obviously it also has limitations.

--
pgas @ SDF Public Access UNIX System - http://sdf.lonestar.org

Re: zsh: STDERR to a variable?

am 30.01.2008 06:22:03 von Barry Margolin

In article <479ee666$0$879$ba4acef3@news.orange.fr>,
Stephane Chazelas wrote:

> On Mon, 28 Jan 2008 21:06:17 -0500, Barry Margolin wrote:
> [...]
> >> If you want both stdout and stderr, it's simpler:
> >>
> >> out_and_err=$(foo bar baz 2>&1)
> >
> > But if you want them in separate variables, you need to write one of
> > them to a temp file or pipe.
>
> (I suppose you meant named pipe as stdout inside $(...) is a
> pipe).

I was also thinking of coroutines, although I'm not really sure if the
syntax would allow for separate stdout and stderr pipes.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***