zsh-users
 help / Atom feed
* Capture stdout, stdin, and exit status in different variables without using temporary files
@ 2019-08-15 15:52 Aryn Starr
  0 siblings, 0 replies; 7+ messages in thread
From: Aryn Starr @ 2019-08-15 15:52 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 250 bytes --]

Per http://mywiki.wooledge.org/BashFAQ/002, it seems this can not be done in bash. Is it possible in zsh?
If not, is a named pipe advantageous to a temporary file?
Is there a way to avoid disk IO (which will probably slow things down considerably)?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Capture stdout, stdin, and exit status in different variables without using temporary files
       [not found] <D639E5A6-A28C-40EE-B0E6-27BED4C8CDDB__31117.9253900022$1565917892$gmane$org@icloud.com>
@ 2019-08-16  7:22 ` Stephane Chazelas
  2019-08-16 10:05 ` Stephane Chazelas
  1 sibling, 0 replies; 7+ messages in thread
From: Stephane Chazelas @ 2019-08-16  7:22 UTC (permalink / raw)
  To: Aryn Starr; +Cc: zsh-users

2019-08-15 20:22:38 +0430, Aryn Starr:
> Per http://mywiki.wooledge.org/BashFAQ/002, it seems this can not be done in bash. Is it possible in zsh?
> If not, is a named pipe advantageous to a temporary file?
> Is there a way to avoid disk IO (which will probably slow things down considerably)?

See

https://unix.stackexchange.com/questions/472585/read-write-to-the-same-file-descriptor-with-shell-redirection/473402#473402

(and
https://unix.stackexchange.com/questions/430161/redirect-stderr-and-stdout-to-different-variables-without-temporary-files
)

Redirecting to files doesn't necessarily mean disk I/O.

-- 
Stephane

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Capture stdout, stdin, and exit status in different variables without using temporary files
       [not found] <D639E5A6-A28C-40EE-B0E6-27BED4C8CDDB__31117.9253900022$1565917892$gmane$org@icloud.com>
  2019-08-16  7:22 ` Stephane Chazelas
@ 2019-08-16 10:05 ` Stephane Chazelas
  2019-08-16 10:45   ` Aryn Starr
  1 sibling, 1 reply; 7+ messages in thread
From: Stephane Chazelas @ 2019-08-16 10:05 UTC (permalink / raw)
  To: Aryn Starr; +Cc: zsh-users

I assume you meant stderr and not stdin which would make little
sense. And the bash wiki pages refers to capturing both stdout
and err, not stdin (whatever that means).

2019-08-15 20:22:38 +0430, Aryn Starr:
> If not, is a named pipe advantageous to a temporary file?

With named pipes, you'd get deadlocks unless you use a
select()/poll() loop like for unnamed pipes.

> Is there a way to avoid disk IO (which will probably slow things down considerably)?

To expand on the solution in the link I gave earlier to also
capture the exit status, that would be:

<<
#! /bin/zsh -
zmodload zsh/zselect
zmodload zsh/system

(){exec {wo}>$1 {ro}<$1} <(:) # like yash's wo>>|ro (but on Linux only)
(){exec {we}>$1 {re}<$1} <(:)

# the command (here ls as an example)
ls -d / /x >&$wo 2>&$we & pid=$!

exec {wo}>&- {we}>&-
out= err=
o_done=0 e_done=0

while ((! (o_done && e_done))) && zselect -A ready $ro $re; do
  if ((${#ready[$ro]})); then
    sysread -i $ro && out+=$REPLY || o_done=1
  fi
  if ((${#ready[$re]})); then
    sysread -i $re && err+=$REPLY || e_done=1
  fi
done
wait "$pid"; exit_status=$?

printf '%s: %s\n' stdout "$out" stderr "$err" 'exit status' "$exit_status"
>>

Which gives:

stdout: /

stderr: ls: cannot access '/x': No such file or directory

exit status: 2

(note that in $out and $err, the trailing newline character is
not removed).

-- 
Stephane

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Capture stdout, stdin, and exit status in different variables without using temporary files
  2019-08-16 10:05 ` Stephane Chazelas
@ 2019-08-16 10:45   ` Aryn Starr
  2019-08-16 13:01     ` TJ Luoma
  0 siblings, 1 reply; 7+ messages in thread
From: Aryn Starr @ 2019-08-16 10:45 UTC (permalink / raw)
  To: Stephane Chazelas; +Cc: zsh-users

Thanks! I read those links and reached two conclusions: That I should this `yash` out. And that I should look for ways to create files on memory.

(I meant stderr, \(ᵔᵕᵔ)/ )

> On Aug 16, 2019, at 2:35 PM, Stephane Chazelas <stephane.chazelas@gmail.com> wrote:
> 
> I assume you meant stderr and not stdin which would make little
> sense. And the bash wiki pages refers to capturing both stdout
> and err, not stdin (whatever that means).
> 
> 2019-08-15 20:22:38 +0430, Aryn Starr:
>> If not, is a named pipe advantageous to a temporary file?
> 
> With named pipes, you'd get deadlocks unless you use a
> select()/poll() loop like for unnamed pipes.
> 
>> Is there a way to avoid disk IO (which will probably slow things down considerably)?
> 
> To expand on the solution in the link I gave earlier to also
> capture the exit status, that would be:
> 
> <<
> #! /bin/zsh -
> zmodload zsh/zselect
> zmodload zsh/system
> 
> (){exec {wo}>$1 {ro}<$1} <(:) # like yash's wo>>|ro (but on Linux only)
> (){exec {we}>$1 {re}<$1} <(:)
> 
> # the command (here ls as an example)
> ls -d / /x >&$wo 2>&$we & pid=$!
> 
> exec {wo}>&- {we}>&-
> out= err=
> o_done=0 e_done=0
> 
> while ((! (o_done && e_done))) && zselect -A ready $ro $re; do
>  if ((${#ready[$ro]})); then
>    sysread -i $ro && out+=$REPLY || o_done=1
>  fi
>  if ((${#ready[$re]})); then
>    sysread -i $re && err+=$REPLY || e_done=1
>  fi
> done
> wait "$pid"; exit_status=$?
> 
> printf '%s: %s\n' stdout "$out" stderr "$err" 'exit status' "$exit_status"
>>> 
> 
> Which gives:
> 
> stdout: /
> 
> stderr: ls: cannot access '/x': No such file or directory
> 
> exit status: 2
> 
> (note that in $out and $err, the trailing newline character is
> not removed).
> 
> -- 
> Stephane


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Capture stdout, stdin, and exit status in different variables without using temporary files
  2019-08-16 10:45   ` Aryn Starr
@ 2019-08-16 13:01     ` TJ Luoma
  2019-08-16 13:16       ` Roman Perepelitsa
  0 siblings, 1 reply; 7+ messages in thread
From: TJ Luoma @ 2019-08-16 13:01 UTC (permalink / raw)
  To: Aryn Starr; +Cc: Zsh MailingList

I have used this, which I am sure someone on the zsh probably gave me:

(){ STDOUT=$( your-command-here 2> $1) STDERR=$(<$1);} =(:)

Using an actual example… I know that `find -x / -maxdepth 4 -print`
will provide both kinds of output, so if I use that here:

(){ STDOUT=$( find -x / -maxdepth 4 -print 2> $1) STDERR=$(<$1);} =(:)

then I can use $STDOUT and $STDERR to get the respective outputs.

I hope that helps!

Tj

--
TJ Luoma
TJ @ MacStories
Personal Website: luo.ma (aka RhymesWithDiploma.com)
Twitter: @tjluoma

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Capture stdout, stdin, and exit status in different variables without using temporary files
  2019-08-16 13:01     ` TJ Luoma
@ 2019-08-16 13:16       ` Roman Perepelitsa
  2019-08-16 17:08         ` TJ Luoma
  0 siblings, 1 reply; 7+ messages in thread
From: Roman Perepelitsa @ 2019-08-16 13:16 UTC (permalink / raw)
  To: TJ Luoma; +Cc: Aryn Starr, Zsh MailingList

[-- Attachment #1: Type: text/plain, Size: 748 bytes --]

On Fri, Aug 16, 2019 at 3:03 PM TJ Luoma <luomat@gmail.com> wrote:

> I have used this, which I am sure someone on the zsh probably gave me:
>
> (){ STDOUT=$( your-command-here 2> $1) STDERR=$(<$1);} =(:)
>

The OP is asking for a solution that doesn't use temporary files, so this
doesn't fit.

FWIW, this recipe is what I use when I need to capture stdout and stderr.
It works great. On modern Linux distros /tmp is usually on an in-memory
filesystem, so no disk IO happens when you are using temporary files. Even
when you have to hit disk, modern SSDs are very fast, with read/write
speeds over 3GB per second. Having sequential SSD reads/writes as a
bottleneck is a tough task even for C code and virtually impossible for zsh
scripts.

Roman.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Capture stdout, stdin, and exit status in different variables without using temporary files
  2019-08-16 13:16       ` Roman Perepelitsa
@ 2019-08-16 17:08         ` TJ Luoma
  0 siblings, 0 replies; 7+ messages in thread
From: TJ Luoma @ 2019-08-16 17:08 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Aryn Starr, Zsh MailingList

>> (){ STDOUT=$( your-command-here 2> $1) STDERR=$(<$1);} =(:)
>
> The OP is asking for a solution that doesn't use temporary files, so this doesn't fit.

My apologies, I didn't realize that this method used temporary files.

TjL

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, back to index

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-15 15:52 Capture stdout, stdin, and exit status in different variables without using temporary files Aryn Starr
     [not found] <D639E5A6-A28C-40EE-B0E6-27BED4C8CDDB__31117.9253900022$1565917892$gmane$org@icloud.com>
2019-08-16  7:22 ` Stephane Chazelas
2019-08-16 10:05 ` Stephane Chazelas
2019-08-16 10:45   ` Aryn Starr
2019-08-16 13:01     ` TJ Luoma
2019-08-16 13:16       ` Roman Perepelitsa
2019-08-16 17:08         ` TJ Luoma

zsh-users

Archives are clonable: git clone --mirror http://inbox.vuxu.org/zsh-users

Newsgroup available over NNTP:
	nntp://inbox.vuxu.org/vuxu.archive.zsh.users


AGPL code for this site: git clone https://public-inbox.org/ public-inbox