Search code examples
bashstdoutstderrsubshell

How to capture / redirect stdout/stderr from a source command into a variable (in a bash script)?


Usually I capture the output via a subshell: result="$(command 2>&1)"

If the command is source, the subshell swallows some (all?) changes to the scripts shell's environment.

How can I capture the output of source into a variable?


Solution

  • Surprisingly tricky question!

    My first thought was to use a named pipe (mkfifo(1)), but those have a finite buffer size, so if the sourced script fills up the buffer the script would hang. And you can't use a background process to drain the buffer because you want the output in a variable in the original process eventually.

    I'm sure there's a way to make it work entirely in memory, but in the end I think a simple and stupid redirect to a temporary file is the most straightforward and robust solution:

    OUTPUT_FILE=$(mktemp)
    source other_script.sh >$OUTPUT_FILE 2>&1
    OUTPUT="$(< "$OUTPUT_FILE")"
    rm -f "$OUTPUT_FILE"
    

    (See this question and in particular BashFAQ 062 for security implications of mktemp though.)