This blog has been archived.
Visit my home page at

Zsh: save stdout, stderr, and return value of command to different variables (without temp file)

This is something worth sharing. The idea was based on this SO answer, and I cooked up this particular implementation to remove potential race conditions, with input from Mathias Fredriksson1. See mafredri/zsh-async#1, and in particular this comment for explanation.

# The following construct evaluates "$@" and saves output on stdout in the
# parameter stdout, output on stderr in the parameter stderr, and return value
# in the parameter return.
# The idea was based on, but this
# implementation is completely race-condition-free. The implementation was
# refined during my exchange with Mathias Fredriksson @mafredri, in
# See mainly
#, where
# the advantage of this implementation is explained.

unset stdout stderr ret
eval "
        stdout=$(eval "$@")
        typeset -p stdout ret
    } 2> >(stderr=$(cat); typeset -p stderr)

Also available as a gist.

  1. Mathias (@mafredri) is the author of the lovely zsh-async library, and a maintainer of sindresorhus/pure. He forever revolutionalized my prompt.↩︎