4

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?

pico_prob
  • 835
  • 8
  • 13

1 Answers1

9

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.)

Thomas
  • 162,537
  • 44
  • 333
  • 446
  • 1
    I think this is an nifty, clean solution. I don't mind leaving the RAM for a moment :) I liked it from the beginning, only marked now as 'accepted' to wait for other answers. – pico_prob Apr 22 '21 at 09:14