7

Right now, I'm trying to nest one bash function call inside another function call (so that the output of one function is used as the input for another function). Is it possible to nest function calls in bash, as I'm trying to do here?

First, I defined these two functions:

returnSomething()
{
    return 5;
}

funky ()
{
  echo $1;
}

Then, I tried to use the output of one function as the input for the other function. However, this next statement doesn't print the output of returnSomething. Instead, it prints nothing at all.

funky $returnSomething; #Now I'm trying to use the output of returnSomething as the input for funky.
5
  • Try just funky returnSomething. $returnSomething is a variable, not a call to the function. Commented May 1, 2013 at 20:08
  • 1
    see this Commented May 1, 2013 at 20:09
  • 1
    funky $(returnSomething) Commented May 1, 2013 at 20:09
  • 1
    @Kevin This doesn't seem to make any difference: it still prints nothing at all. Commented May 1, 2013 at 20:12
  • @fedorqui In that case, it would only print the string returnSomething to the console. Commented May 1, 2013 at 20:13

3 Answers 3

10

You have two problems. One is that return does not set the output of a function, but rather its exit status (zero for success, nonzero for failure). For example, echo foo will output foo (plus a newline), but has an exit status of 0. To control output, use echo or printf:

function returnSomething ()     # should actually be outputSomething
{
    echo 5
}

The other problem is that $returnSomething (or ${returnSomething}) gives the value of a variable named returnSomething:

x=5          # sets the variable x
echo "$x"    # outputs 5

To capture the output of a command, use the notation $(...) (or `...`, but the latter is trickier). So:

function funky ()
{
    echo "$( "$1" )"
}
funky returnSomething    # prints 5

or just:

function funky ()
{
    "$1"          # runs argument as a command
}
funky returnSomething    # prints 5

By contrast, if you do want to capture the exit status of a command, use the special shell parameter ? (which is set to the exit status of a command when it completes):

function returnSomething ()
{
    return 5
}
function funky ()
{
    "$1"          # runs argument as a command
    echo "$?"     # prints its exit status
}
funky returnSomething    # prints 5
Sign up to request clarification or add additional context in comments.

12 Comments

I still haven't figured out how to nest one function call (with parameters) inside another function call. For example, (sampleFunction2 (sampleFunction1 "Parameter for sample function 1")) produces syntax error near unexpected token sampleFunction1'. Is it possible to make nested function calls like this one?
@AndersonGreen: I'm not sure I understand what you're asking; Bash commands support a greater variety of possible interactions than functions in other languages, so there are multiple ways to combine them that could all be called "nesting". My best guess is, maybe you want the output of the command sampleFunction1 "Parameter for sample function 1" to be captured (instead of going to the console, as it normally would), and you want that output to be passed as an argument (a parameter) to the function sampleFunction2. Is that right? If so, you can write (continued)
(continued) sampleFunction2 "$(sampleFunction1 "Parameter for sample function 1")".
@AndersonGreen: By the way, all of this is explained in detail in the Bash Reference Manual; see gnu.org/software/bash/manual/bashref.html#Command-Substitution.
@AndersonGreen: Regarding double-quotes: it's always a good idea to wrap expansions such as $(...) in double-quotes, so that even if they misbehave and output something different than you expect, you can at least be sure they'll end up as the right number of parameters. (Consider something like cp foo.txt bar.txt $(baz), which is supposed to copy foo.txt and bar.txt into the directory that baz says to -- but if baz (say) errors out and doesn't print any directory at all, then this will overwrite bar.txt with a copy of foo.txt.)
|
3

Bash substitutes $(command) with the output of command, so you can use funky $(returnSomething) to pass funky the output of returnSomething. However, it looks like you're misunderstanding return in bash; the return value is a number that indicates whether the call was successful. The way to get the return status of the last process in bash is $?:

returnSomething
funky $?

4 Comments

Does this mean that it's basically impossible for a function in Bash to return any kind of non-integer value?
Yes, you have to print it and capture the output, or set a variable (though there are a number of gotchas around that)
What are those "gotchas", specifically?
If you put a call in a subshell (either as part of a pipe, an explicit subshell, or a $(...) subshell), it won't affect the caller's environment. This especially gets people in loops. You have to declare the variable before the function.
0

How about this:

function foo() { echo one two three; }
function bar() { echo foo #1: $1 }
bar $( foo ) # ==> foo #1: one

The above has problem, thanks to Anderson for pointing it out. Here is an update:

function foo() { echo one two three; }
function bar() { echo foo $1; }
bar $( foo )

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.