12

In bash scripts I try to keep my variables local to functions wherever I can and then pass what I need out of functions like bellow

#!/bin/bash

function FUNCTION() {
    local LOCAL="value"
    echo "$LOCAL"   # return this variable
}

GLOBAL=$(FUNCTION)

echo "$GLOBAL"

But is it possible to do this while including the function's own echos so that if the function has it's own messages to output I don't have to catch them in a variable

#!/bin/bash

function FUNCTION() {
    local LOCAL="value"
    echo "$LOCAL"                      # return this variable
    echo "This function is done now"   # do not return this variable
}

GLOBAL=$(FUNCTION)

echo "$GLOBAL"                         # should only echo 'value'
  • 1
    Hey why are you guys all using the old, non-POSIX function foo() syntax? You can get better POSIX compatibility with 9 less keypunches. – Arthur2e5 Oct 15 '15 at 12:44
  • 2
    This syntax is just more familiar to me – TheLovelySausage Oct 15 '15 at 14:49
  • 1
    @Arthur2e5 primarily because it's easier to type "function" than "[a-zA-Z0-9]+\(\) \{" when searching through the code – Alex Jansen Feb 12 at 22:47
15

Anything that's printed by the function can be captured if you capture the right output stream. So the easiest way to print something and save some other output is to redirect the superfluous output to standard error:

function FUNCTION() {
    local LOCAL="value"
    echo "$LOCAL"
    echo "This function is done now" >&2
}

Another possibility is to log to a file rather than printing log messages directly, for example using something like this:

log() {
    printf '%s\n' "$@" > my.log
}

That said, Bash functions cannot return variables. The only actual "return" value is the exit code. For this reason (and many others), if you want reliable logging, return values, exception handling and more you'll want to use a different language like Python, Ruby or Java.

4

You can present info messages on standard error:

function FUNCTION() {
    local LOCAL="value"
    echo "$LOCAL"                      # return this variable
    echo "This function is done now" > /dev/stderr  # goes to the screen
}

Some other suggestions are in this Linux Journal article: use global variables (which you mentioned you don't prefer), or pass the name of the variable to return the result in.

  • /dev/stderr points to fd 2 and can still be redirected by &>blah or 2>blah. /dev/tty may be better. – Arthur2e5 Oct 15 '15 at 12:43

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.