Here's the code:

#! /bin/bash

function foo() {
  echo "ReturnVal"

echo "RV=$RV, G1=$G1"  # RV=ReturnVal, G1=

foo >/dev/null
echo "G1=$G1"  # G1=123

I want to execute the function, set global variable G1, AND capture the stdout of the function into a variable.

The first call fails to set the global variable because the function is executing in a subshell. But that's the canonical way to get stdout into a variable.

I realize the 2nd call to foo() is throwing away stdout. Writing it to the console is equally pointless for my purpose. But it illustrates that the function is capable of setting the global variable.

Note that any solution cannot use a temporary file on the filesystem. The function I'm actually trying to write is already dealing with temp files and their automatic cleanup; introducing another temp file is not an option.

Is there a way?


Are you coming from Java, C++? That doesn't look any BASH I've ever seen.


  echo eval "
  echo \"My function \$G1\"; "

myVar=$(myFunction 2>&1);
source <(myFunction) 2>&1 >/dev/null;
echo "G1: $G1";
eval echo "myVar: $(grep -v eval <($myVar))"

Very messy because exporting variables from a subprocess to its parent isn't allowed.

G1: 123
myVar: My function 123
| improve this answer | |
  • Thanks for the response. Unfortunately, the function that I would graft this solution onto accumulates its arguments in the G1 variable. So calling the function twice each time will add undesired complexity to work around that. Also, the function is meant to encapsulate the complexity for the benefit of my simple, non-bashy users, and I would not inflict your calling syntax on them. You have a solution that works, just not for me. Btw, I've been writing shell scripts for decades, not sure what you've seen. – MykennaC Aug 7 '13 at 16:28
  • The solution I ended up using was to use two separate functions. The "inline" function set the global variable, and the "subshell" function returned data in stdout. My actual use case was a function that was trying to do two things: generate and return a temporary filename while maintaining a global variable of all generated filenames. Although I didn't end up using the above answer, I appreciate the effort to find something that works (and validate the difficulty of the problem). – MykennaC Oct 18 '13 at 15:07

I ran into this problem myself recently, but in my case I couldn't separate my code into two separate functions, nor could I predict the name of the global variable I was going to set.

The following is what I came up with. The calling syntax is different, but easy enough. It may require some fiddling with backslash escapes, however.

Basically, it works like read, but while setting a global at the same time.

#!/usr/bin/env bash

function do_your_thing() {
    local name_of_capture_var="${1}"

    global_var="global global global global global"
    normally_sent_to_stdout="stdout stdout stdout stdout"

    eval "${name_of_capture_var}=\"${normally_sent_to_stdout}\""

function main() {
    local capture

    do_your_thing capture

    echo "In main():"
    echo "capture: ${capture}"
    echo "global_var: ${global_var}"


echo "Outside of main()"
echo "capture: ${capture}"
echo "global_var: ${global_var}"
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.