Return value in a Bash functionBash function can't return large numbersbash function failed to give a return valueHow can I save the result of a function in a variable in BASH?Passing parameters to a Bash functionHow to return a string value from a Bash functionShell Script to Generate Fibonacci SeriesWhat's the difference between echo and return in bash?Preserve return value and run not from subshellObtaining an integer (greater than 255) from the system function in C++How can I directly put a return value of a bash function into an if-statement?Get the source directory of a Bash script from within the script itselfHow to check if a string contains a substring in Bashvar functionName = function() vs function functionName() How to return multiple values from a function?How to check if a program exists from a Bash script?How do I tell if a regular file does not exist in Bash?Set a default parameter value for a JavaScript functionExtract filename and extension in BashHow to concatenate string variables in BashEcho newline in Bash prints literal n

Why other Westeros houses don't use wildfire?

What is the relationship between spectral sequences and obstruction theory?

Error message with tabularx

Will tsunami waves travel forever if there was no land?

Will a top journal at least read my introduction?

Does Gita support doctrine of eternal cycle of birth and death for evil people?

What does KSP mean?

Why does academia still use scientific journals and not peer-reviewed government funded alternatives?

What's the polite way to say "I need to urinate"?

Please, smoke with good manners

What are the potential pitfalls when using metals as a currency?

Was there a shared-world project before "Thieves World"?

What makes accurate emulation of old systems a difficult task?

How do I deal with a coworker that keeps asking to make small superficial changes to a report, and it is seriously triggering my anxiety?

Does a semiconductor follow Ohm's law?

How to solve constants out of the internal energy equation?

Critique of timeline aesthetic

How to have a sharp product image?

Why do Computer Science majors learn Calculus?

Reducing vertical space in stackrel

What do the phrase "Reeyan's seacrest" and the word "fraggle" mean in a sketch?

Why isn't the definition of absolute value applied when squaring a radical containing a variable?

What does it mean to express a gate in Dirac notation?

Repelling Blast: Must targets always be pushed back?



Return value in a Bash function


Bash function can't return large numbersbash function failed to give a return valueHow can I save the result of a function in a variable in BASH?Passing parameters to a Bash functionHow to return a string value from a Bash functionShell Script to Generate Fibonacci SeriesWhat's the difference between echo and return in bash?Preserve return value and run not from subshellObtaining an integer (greater than 255) from the system function in C++How can I directly put a return value of a bash function into an if-statement?Get the source directory of a Bash script from within the script itselfHow to check if a string contains a substring in Bashvar functionName = function() vs function functionName() How to return multiple values from a function?How to check if a program exists from a Bash script?How do I tell if a regular file does not exist in Bash?Set a default parameter value for a JavaScript functionExtract filename and extension in BashHow to concatenate string variables in BashEcho newline in Bash prints literal n






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








220















I am working with a bash script and I want to execute a function to print a return value:



function fun1()
return 34

function fun2()
local res=$(fun1)
echo $res



When I execute fun2, it does not print "34". Why is this the case?










share|improve this question



















  • 7





    return in your case is essentially the same as exit code which range from 0 - 255. Use echo as suggested by @septi. Exit codes can be captured with $?.

    – devnull
    Jun 27 '13 at 7:26







  • 1





    In this case it is much more flexible to already use echo in fun1. It’s the idea of unix-programming: echo sends the results to standard output which then can be reused by other functions with res=$(fun1) - or directly be piped to other functions: function a() echo 34; function b() while read data; do echo $data ; done ; a | b

    – Arne Babenhauserheide
    Jan 8 '14 at 22:37











  • The proper way to do this is to put the top level stuff in a function and use a local with bash's dynamic scoping rule. I'll create an answer to demonstrate, it is not a well-known feature but one fully supported.

    – Oliver
    Aug 29 '18 at 15:47

















220















I am working with a bash script and I want to execute a function to print a return value:



function fun1()
return 34

function fun2()
local res=$(fun1)
echo $res



When I execute fun2, it does not print "34". Why is this the case?










share|improve this question



















  • 7





    return in your case is essentially the same as exit code which range from 0 - 255. Use echo as suggested by @septi. Exit codes can be captured with $?.

    – devnull
    Jun 27 '13 at 7:26







  • 1





    In this case it is much more flexible to already use echo in fun1. It’s the idea of unix-programming: echo sends the results to standard output which then can be reused by other functions with res=$(fun1) - or directly be piped to other functions: function a() echo 34; function b() while read data; do echo $data ; done ; a | b

    – Arne Babenhauserheide
    Jan 8 '14 at 22:37











  • The proper way to do this is to put the top level stuff in a function and use a local with bash's dynamic scoping rule. I'll create an answer to demonstrate, it is not a well-known feature but one fully supported.

    – Oliver
    Aug 29 '18 at 15:47













220












220








220


49






I am working with a bash script and I want to execute a function to print a return value:



function fun1()
return 34

function fun2()
local res=$(fun1)
echo $res



When I execute fun2, it does not print "34". Why is this the case?










share|improve this question
















I am working with a bash script and I want to execute a function to print a return value:



function fun1()
return 34

function fun2()
local res=$(fun1)
echo $res



When I execute fun2, it does not print "34". Why is this the case?







bash function return-value






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 11 '18 at 21:45









learningbee

122110




122110










asked Jun 27 '13 at 7:17









mindiamindia

1,48431519




1,48431519







  • 7





    return in your case is essentially the same as exit code which range from 0 - 255. Use echo as suggested by @septi. Exit codes can be captured with $?.

    – devnull
    Jun 27 '13 at 7:26







  • 1





    In this case it is much more flexible to already use echo in fun1. It’s the idea of unix-programming: echo sends the results to standard output which then can be reused by other functions with res=$(fun1) - or directly be piped to other functions: function a() echo 34; function b() while read data; do echo $data ; done ; a | b

    – Arne Babenhauserheide
    Jan 8 '14 at 22:37











  • The proper way to do this is to put the top level stuff in a function and use a local with bash's dynamic scoping rule. I'll create an answer to demonstrate, it is not a well-known feature but one fully supported.

    – Oliver
    Aug 29 '18 at 15:47












  • 7





    return in your case is essentially the same as exit code which range from 0 - 255. Use echo as suggested by @septi. Exit codes can be captured with $?.

    – devnull
    Jun 27 '13 at 7:26







  • 1





    In this case it is much more flexible to already use echo in fun1. It’s the idea of unix-programming: echo sends the results to standard output which then can be reused by other functions with res=$(fun1) - or directly be piped to other functions: function a() echo 34; function b() while read data; do echo $data ; done ; a | b

    – Arne Babenhauserheide
    Jan 8 '14 at 22:37











  • The proper way to do this is to put the top level stuff in a function and use a local with bash's dynamic scoping rule. I'll create an answer to demonstrate, it is not a well-known feature but one fully supported.

    – Oliver
    Aug 29 '18 at 15:47







7




7





return in your case is essentially the same as exit code which range from 0 - 255. Use echo as suggested by @septi. Exit codes can be captured with $?.

– devnull
Jun 27 '13 at 7:26






return in your case is essentially the same as exit code which range from 0 - 255. Use echo as suggested by @septi. Exit codes can be captured with $?.

– devnull
Jun 27 '13 at 7:26





1




1





In this case it is much more flexible to already use echo in fun1. It’s the idea of unix-programming: echo sends the results to standard output which then can be reused by other functions with res=$(fun1) - or directly be piped to other functions: function a() echo 34; function b() while read data; do echo $data ; done ; a | b

– Arne Babenhauserheide
Jan 8 '14 at 22:37





In this case it is much more flexible to already use echo in fun1. It’s the idea of unix-programming: echo sends the results to standard output which then can be reused by other functions with res=$(fun1) - or directly be piped to other functions: function a() echo 34; function b() while read data; do echo $data ; done ; a | b

– Arne Babenhauserheide
Jan 8 '14 at 22:37













The proper way to do this is to put the top level stuff in a function and use a local with bash's dynamic scoping rule. I'll create an answer to demonstrate, it is not a well-known feature but one fully supported.

– Oliver
Aug 29 '18 at 15:47





The proper way to do this is to put the top level stuff in a function and use a local with bash's dynamic scoping rule. I'll create an answer to demonstrate, it is not a well-known feature but one fully supported.

– Oliver
Aug 29 '18 at 15:47












9 Answers
9






active

oldest

votes


















288














Although bash has a return statement, the only thing you can specify with it is the function's own exit status (a value between 0 and 255, 0 meaning "success"). So return is not what you want.



You might want to convert your return statement to an echo statement - that way your function output could be captured using $() braces, which seems to be exactly what you want.



Here is an example:



function fun1()
echo 34


function fun2()
local res=$(fun1)
echo $res



Another way to get the return value (if you just want to return an integer 0-255) is $?.



function fun1()
return 34


function fun2()
fun1
local res=$?
echo $res



Also, note that you can use the return value to use boolean logic like fun1 || fun2 will only run fun2 if fun1 returns a 0 value. The default return value is the exit value of the last statement executed within the function.






share|improve this answer




















  • 5





    +1 for not suggesting $? outright.

    – devnull
    Jun 27 '13 at 7:28






  • 9





    Why not use $??

    – Pithikos
    Aug 29 '14 at 17:48






  • 84





    No, I need the damn return value. To hell with echo.

    – Tomáš Zato
    Apr 21 '15 at 19:29






  • 5





    @Blauhirn in this environment, with this || construct, an exit code of 0 is considered success and therefore "true". Non-zero is error and therefore false. Think of fun1 || fun2 as shorthand for "if fun1 returns success or fun2 returns success" rather than an operator on the actual return values themselves.

    – davidA
    Mar 30 '16 at 21:08






  • 3





    What's annoying is that a function that should provide data cannot also echo other stuff to stdout, because the caller using $() will receive that too and get confused or have to parse the output. Global variables are not great because it's just a matter of time before you use the same global var in two places that happen to be nested and data could get lost. There should be separate channels for printing data vs sending data back.

    – Oliver
    Aug 2 '18 at 22:19


















58














$(...) captures the text sent to stdout by the command contained within. return does not output to stdout. $? contains the result code of the last command.



fun1 ()
return 34


fun2 ()
fun1
local res=$?
echo $res






share|improve this answer























  • and return is a result code?

    – Blauhirn
    Mar 31 '16 at 11:23






  • 4





    Yes return is used for setting $? which is the exit status. In the above example, fun1's exit status would be 34. Also, note that $(...) also captures stderr in addition to stdout from command specified.

    – swoop81
    Nov 27 '17 at 21:33



















42














Functions in Bash are not functions like in other language; they're actually commands. So functions are used as if they were binaries or scripts fetched from your path. From the perspective of your program logic there should be really no difference.



Shell commands are connected by pipes (aka streams), and not fundamental or user-defined data types, as in "real" programming languages. There is no such thing like a return value for a command, maybe mostly because there's no real way to declare it. It could occur on the man-page, or the --help output of the command, but both are only human-readable and hence are written to the wind.



When a command wants to get input it reads it from its input stream, or the argument list. In both cases text strings have to be parsed.



When a command wants to return something it has to echo it to its output stream. Another oftenly practiced way is to store the return value in dedicated, global variables. Writing to the output stream is clearer and more flexible, because it can take also binary data. For example, you can return a BLOB easily:



encrypt() 
gpg -c -o- $1 # encrypt data in filename to stdout (asks for a passphrase)


encrypt public.dat > private.dat # write function result to file


As others have written in this thread, the caller can also use command substitution $() to capture the output.



Parallely, the function would "return" the exit code of gpg (GnuPG). Think of the exit code as a bonus that other languages don't have, or, depending on your temperament, as a "Schmutzeffekt" of shell functions. This status is, by convention, 0 on success or an integer in the range 1-255 for something else. To make this clear: return (like exit) can only take a value from 0-255, and values other than 0 are not necessarily errors, as is often asserted.



When you don't provide an explicit value with return the status is taken from the last command in a Bash statement/function/command and so forth. So there is always a status, and return is just an easy way to provide it.






share|improve this answer




















  • 1





    +1 for explaining functions vs commands and how this impacts the notion of sending data back to the caller

    – Oliver
    Aug 2 '18 at 22:16






  • 1





    +1 for explaining that shell programming is about connecting commands via pipes. Other programming languages compose functions via return types. Bash composes commands via streams of text.

    – jrahhali
    Nov 2 '18 at 0:10


















23














The return statement sets the exit code of the function, much the same as exit will do for the entire script.



The exit code for the last command is always available in the $? variable.



function fun1()
return 34


function fun2()
local res=$(fun1)
echo $? # <-- Always echos 0 since the 'local' command passes.

res=$(fun1)
echo $? #<-- Outputs 34






share|improve this answer






























    5














    I like to do the following if running in a script where the function is defined:



    POINTER= # used for function return values

    my_function()
    # do stuff
    POINTER="my_function_return"


    my_other_function()
    # do stuff
    POINTER="my_other_function_return"


    my_function
    RESULT="$POINTER"

    my_other_function
    RESULT="$POINTER"


    I like this, becase I can then include echo statements in my functions if I want



    my_function() 
    echo "-> my_function()"
    # do stuff
    POINTER="my_function_return"
    echo "<- my_function. $POINTER"






    share|improve this answer
































      4














      Another way to achive this is name references (requires Bash 4.3+).



      function example 
      local -n VAR=$1
      VAR=foo


      example RESULT
      echo $RESULT





      share|improve this answer


















      • 1





        Wow I did not know about this, thanks for sharing.

        – Oliver
        Jan 18 at 18:23


















      4














      The problem with other answers is they either use a global, which can be overwritten when several functions are in a call chain, or echo which means your function cannot output diagnostic info (you will forget your function does this and the "result", ie return value, will contain more info than your caller expects, leading to weird bug), or eval which is way heavy and hacky.



      The proper way to do this is to put the top level stuff in a function and use a local with bash's dynamic scoping rule. Example:



      func1() 

      ret_val=hi


      func2()

      ret_val=bye


      func3()

      local ret_val=nothing
      echo $ret_val
      func1
      echo $ret_val
      func2
      echo $ret_val


      func3


      This outputs



      nothing
      hi
      bye


      Dynamic scoping means that ret_val points to a different object depending on the caller! This is different from lexical scoping, which is what most programming languages use. This is actually a documented feature, just easy to miss, and not very well explained, here is the docs for it (emphasis is mine):




      Variables local to the function may be declared with the local
      builtin. These variables are visible only to the function and the
      commands it invokes
      .




      For someone with a C/C++/Python/Java/C#/javascript background, this is probably the biggest hurdle: functions in bash are not functions, they are commands, and behave as such: they can output to stdout/stderr, they can pipe in/out, they can return an exit code. Basically there is no difference between defining a command in a script and creating an executable that can be called from the command.



      So instead of writing your script like this:



      top-level code 
      bunch of functions
      more top-level code


      write it like this:



      # define your main, containing all top-level code
      main()
      bunch of functions
      # call main
      main


      where main() declares ret_val as local and all other functions return values via ret_val.



      See also https://unix.stackexchange.com/questions/282557/scope-of-local-variables-in-shell-functions.



      Another, perhaps even better solution depending on situation, is the one posted by ya.teck which uses local -n.






      share|improve this answer
































        3














        As an add-on to others' excellent posts, here's an article summarizing these techniques:



        • set a global variable

        • set a global variable, whose name you passed to the function

        • set the return code (and pick it up with $?)

        • 'echo' some data (and pick it up with MYVAR=$(myfunction) )

        Returning Values from Bash Functions






        share|improve this answer






























          -2














          Git Bash on Windows using arrays for multiple return values



          BASH CODE:



          #!/bin/bash

          ##A 6-element array used for returning
          ##values from functions:
          declare -a RET_ARR
          RET_ARR[0]="A"
          RET_ARR[1]="B"
          RET_ARR[2]="C"
          RET_ARR[3]="D"
          RET_ARR[4]="E"
          RET_ARR[5]="F"


          function FN_MULTIPLE_RETURN_VALUES()

          ##give the positional arguments/inputs
          ##$1 and $2 some sensible names:
          local out_dex_1="$1" ##output index
          local out_dex_2="$2" ##output index

          ##Echo for debugging:
          echo "running: FN_MULTIPLE_RETURN_VALUES"

          ##Here: Calculate output values:
          local op_var_1="Hello"
          local op_var_2="World"

          ##set the return values:
          RET_ARR[ $out_dex_1 ]=$op_var_1
          RET_ARR[ $out_dex_2 ]=$op_var_2



          echo "FN_MULTIPLE_RETURN_VALUES EXAMPLES:"
          echo "-------------------------------------------"
          fn="FN_MULTIPLE_RETURN_VALUES"
          out_dex_a=0
          out_dex_b=1
          eval $fn $out_dex_a $out_dex_b ##<--Call function
          a=$RET_ARR[0] && echo "RET_ARR[0]: $a "
          b=$RET_ARR[1] && echo "RET_ARR[1]: $b "
          echo
          ##----------------------------------------------##
          c="2"
          d="3"
          FN_MULTIPLE_RETURN_VALUES $c $d ##<--Call function
          c_res=$RET_ARR[2] && echo "RET_ARR[2]: $c_res "
          d_res=$RET_ARR[3] && echo "RET_ARR[3]: $d_res "
          echo
          ##----------------------------------------------##
          FN_MULTIPLE_RETURN_VALUES 4 5 ##<---Call function
          e=$RET_ARR[4] && echo "RET_ARR[4]: $e "
          f=$RET_ARR[5] && echo "RET_ARR[5]: $f "
          echo
          ##----------------------------------------------##


          read -p "Press Enter To Exit:"


          EXPECTED OUTPUT:



          FN_MULTIPLE_RETURN_VALUES EXAMPLES:
          -------------------------------------------
          running: FN_MULTIPLE_RETURN_VALUES
          RET_ARR[0]: Hello
          RET_ARR[1]: World

          running: FN_MULTIPLE_RETURN_VALUES
          RET_ARR[2]: Hello
          RET_ARR[3]: World

          running: FN_MULTIPLE_RETURN_VALUES
          RET_ARR[4]: Hello
          RET_ARR[5]: World

          Press Enter To Exit:





          share|improve this answer





















            protected by codeforester Aug 29 '18 at 16:54



            Thank you for your interest in this question.
            Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



            Would you like to answer one of these unanswered questions instead?














            9 Answers
            9






            active

            oldest

            votes








            9 Answers
            9






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            288














            Although bash has a return statement, the only thing you can specify with it is the function's own exit status (a value between 0 and 255, 0 meaning "success"). So return is not what you want.



            You might want to convert your return statement to an echo statement - that way your function output could be captured using $() braces, which seems to be exactly what you want.



            Here is an example:



            function fun1()
            echo 34


            function fun2()
            local res=$(fun1)
            echo $res



            Another way to get the return value (if you just want to return an integer 0-255) is $?.



            function fun1()
            return 34


            function fun2()
            fun1
            local res=$?
            echo $res



            Also, note that you can use the return value to use boolean logic like fun1 || fun2 will only run fun2 if fun1 returns a 0 value. The default return value is the exit value of the last statement executed within the function.






            share|improve this answer




















            • 5





              +1 for not suggesting $? outright.

              – devnull
              Jun 27 '13 at 7:28






            • 9





              Why not use $??

              – Pithikos
              Aug 29 '14 at 17:48






            • 84





              No, I need the damn return value. To hell with echo.

              – Tomáš Zato
              Apr 21 '15 at 19:29






            • 5





              @Blauhirn in this environment, with this || construct, an exit code of 0 is considered success and therefore "true". Non-zero is error and therefore false. Think of fun1 || fun2 as shorthand for "if fun1 returns success or fun2 returns success" rather than an operator on the actual return values themselves.

              – davidA
              Mar 30 '16 at 21:08






            • 3





              What's annoying is that a function that should provide data cannot also echo other stuff to stdout, because the caller using $() will receive that too and get confused or have to parse the output. Global variables are not great because it's just a matter of time before you use the same global var in two places that happen to be nested and data could get lost. There should be separate channels for printing data vs sending data back.

              – Oliver
              Aug 2 '18 at 22:19















            288














            Although bash has a return statement, the only thing you can specify with it is the function's own exit status (a value between 0 and 255, 0 meaning "success"). So return is not what you want.



            You might want to convert your return statement to an echo statement - that way your function output could be captured using $() braces, which seems to be exactly what you want.



            Here is an example:



            function fun1()
            echo 34


            function fun2()
            local res=$(fun1)
            echo $res



            Another way to get the return value (if you just want to return an integer 0-255) is $?.



            function fun1()
            return 34


            function fun2()
            fun1
            local res=$?
            echo $res



            Also, note that you can use the return value to use boolean logic like fun1 || fun2 will only run fun2 if fun1 returns a 0 value. The default return value is the exit value of the last statement executed within the function.






            share|improve this answer




















            • 5





              +1 for not suggesting $? outright.

              – devnull
              Jun 27 '13 at 7:28






            • 9





              Why not use $??

              – Pithikos
              Aug 29 '14 at 17:48






            • 84





              No, I need the damn return value. To hell with echo.

              – Tomáš Zato
              Apr 21 '15 at 19:29






            • 5





              @Blauhirn in this environment, with this || construct, an exit code of 0 is considered success and therefore "true". Non-zero is error and therefore false. Think of fun1 || fun2 as shorthand for "if fun1 returns success or fun2 returns success" rather than an operator on the actual return values themselves.

              – davidA
              Mar 30 '16 at 21:08






            • 3





              What's annoying is that a function that should provide data cannot also echo other stuff to stdout, because the caller using $() will receive that too and get confused or have to parse the output. Global variables are not great because it's just a matter of time before you use the same global var in two places that happen to be nested and data could get lost. There should be separate channels for printing data vs sending data back.

              – Oliver
              Aug 2 '18 at 22:19













            288












            288








            288







            Although bash has a return statement, the only thing you can specify with it is the function's own exit status (a value between 0 and 255, 0 meaning "success"). So return is not what you want.



            You might want to convert your return statement to an echo statement - that way your function output could be captured using $() braces, which seems to be exactly what you want.



            Here is an example:



            function fun1()
            echo 34


            function fun2()
            local res=$(fun1)
            echo $res



            Another way to get the return value (if you just want to return an integer 0-255) is $?.



            function fun1()
            return 34


            function fun2()
            fun1
            local res=$?
            echo $res



            Also, note that you can use the return value to use boolean logic like fun1 || fun2 will only run fun2 if fun1 returns a 0 value. The default return value is the exit value of the last statement executed within the function.






            share|improve this answer















            Although bash has a return statement, the only thing you can specify with it is the function's own exit status (a value between 0 and 255, 0 meaning "success"). So return is not what you want.



            You might want to convert your return statement to an echo statement - that way your function output could be captured using $() braces, which seems to be exactly what you want.



            Here is an example:



            function fun1()
            echo 34


            function fun2()
            local res=$(fun1)
            echo $res



            Another way to get the return value (if you just want to return an integer 0-255) is $?.



            function fun1()
            return 34


            function fun2()
            fun1
            local res=$?
            echo $res



            Also, note that you can use the return value to use boolean logic like fun1 || fun2 will only run fun2 if fun1 returns a 0 value. The default return value is the exit value of the last statement executed within the function.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Apr 11 '18 at 20:09









            learningbee

            122110




            122110










            answered Jun 27 '13 at 7:19









            tamasgaltamasgal

            14.3k1072116




            14.3k1072116







            • 5





              +1 for not suggesting $? outright.

              – devnull
              Jun 27 '13 at 7:28






            • 9





              Why not use $??

              – Pithikos
              Aug 29 '14 at 17:48






            • 84





              No, I need the damn return value. To hell with echo.

              – Tomáš Zato
              Apr 21 '15 at 19:29






            • 5





              @Blauhirn in this environment, with this || construct, an exit code of 0 is considered success and therefore "true". Non-zero is error and therefore false. Think of fun1 || fun2 as shorthand for "if fun1 returns success or fun2 returns success" rather than an operator on the actual return values themselves.

              – davidA
              Mar 30 '16 at 21:08






            • 3





              What's annoying is that a function that should provide data cannot also echo other stuff to stdout, because the caller using $() will receive that too and get confused or have to parse the output. Global variables are not great because it's just a matter of time before you use the same global var in two places that happen to be nested and data could get lost. There should be separate channels for printing data vs sending data back.

              – Oliver
              Aug 2 '18 at 22:19












            • 5





              +1 for not suggesting $? outright.

              – devnull
              Jun 27 '13 at 7:28






            • 9





              Why not use $??

              – Pithikos
              Aug 29 '14 at 17:48






            • 84





              No, I need the damn return value. To hell with echo.

              – Tomáš Zato
              Apr 21 '15 at 19:29






            • 5





              @Blauhirn in this environment, with this || construct, an exit code of 0 is considered success and therefore "true". Non-zero is error and therefore false. Think of fun1 || fun2 as shorthand for "if fun1 returns success or fun2 returns success" rather than an operator on the actual return values themselves.

              – davidA
              Mar 30 '16 at 21:08






            • 3





              What's annoying is that a function that should provide data cannot also echo other stuff to stdout, because the caller using $() will receive that too and get confused or have to parse the output. Global variables are not great because it's just a matter of time before you use the same global var in two places that happen to be nested and data could get lost. There should be separate channels for printing data vs sending data back.

              – Oliver
              Aug 2 '18 at 22:19







            5




            5





            +1 for not suggesting $? outright.

            – devnull
            Jun 27 '13 at 7:28





            +1 for not suggesting $? outright.

            – devnull
            Jun 27 '13 at 7:28




            9




            9





            Why not use $??

            – Pithikos
            Aug 29 '14 at 17:48





            Why not use $??

            – Pithikos
            Aug 29 '14 at 17:48




            84




            84





            No, I need the damn return value. To hell with echo.

            – Tomáš Zato
            Apr 21 '15 at 19:29





            No, I need the damn return value. To hell with echo.

            – Tomáš Zato
            Apr 21 '15 at 19:29




            5




            5





            @Blauhirn in this environment, with this || construct, an exit code of 0 is considered success and therefore "true". Non-zero is error and therefore false. Think of fun1 || fun2 as shorthand for "if fun1 returns success or fun2 returns success" rather than an operator on the actual return values themselves.

            – davidA
            Mar 30 '16 at 21:08





            @Blauhirn in this environment, with this || construct, an exit code of 0 is considered success and therefore "true". Non-zero is error and therefore false. Think of fun1 || fun2 as shorthand for "if fun1 returns success or fun2 returns success" rather than an operator on the actual return values themselves.

            – davidA
            Mar 30 '16 at 21:08




            3




            3





            What's annoying is that a function that should provide data cannot also echo other stuff to stdout, because the caller using $() will receive that too and get confused or have to parse the output. Global variables are not great because it's just a matter of time before you use the same global var in two places that happen to be nested and data could get lost. There should be separate channels for printing data vs sending data back.

            – Oliver
            Aug 2 '18 at 22:19





            What's annoying is that a function that should provide data cannot also echo other stuff to stdout, because the caller using $() will receive that too and get confused or have to parse the output. Global variables are not great because it's just a matter of time before you use the same global var in two places that happen to be nested and data could get lost. There should be separate channels for printing data vs sending data back.

            – Oliver
            Aug 2 '18 at 22:19













            58














            $(...) captures the text sent to stdout by the command contained within. return does not output to stdout. $? contains the result code of the last command.



            fun1 ()
            return 34


            fun2 ()
            fun1
            local res=$?
            echo $res






            share|improve this answer























            • and return is a result code?

              – Blauhirn
              Mar 31 '16 at 11:23






            • 4





              Yes return is used for setting $? which is the exit status. In the above example, fun1's exit status would be 34. Also, note that $(...) also captures stderr in addition to stdout from command specified.

              – swoop81
              Nov 27 '17 at 21:33
















            58














            $(...) captures the text sent to stdout by the command contained within. return does not output to stdout. $? contains the result code of the last command.



            fun1 ()
            return 34


            fun2 ()
            fun1
            local res=$?
            echo $res






            share|improve this answer























            • and return is a result code?

              – Blauhirn
              Mar 31 '16 at 11:23






            • 4





              Yes return is used for setting $? which is the exit status. In the above example, fun1's exit status would be 34. Also, note that $(...) also captures stderr in addition to stdout from command specified.

              – swoop81
              Nov 27 '17 at 21:33














            58












            58








            58







            $(...) captures the text sent to stdout by the command contained within. return does not output to stdout. $? contains the result code of the last command.



            fun1 ()
            return 34


            fun2 ()
            fun1
            local res=$?
            echo $res






            share|improve this answer













            $(...) captures the text sent to stdout by the command contained within. return does not output to stdout. $? contains the result code of the last command.



            fun1 ()
            return 34


            fun2 ()
            fun1
            local res=$?
            echo $res







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jun 27 '13 at 7:24









            Ignacio Vazquez-AbramsIgnacio Vazquez-Abrams

            595k10710821184




            595k10710821184












            • and return is a result code?

              – Blauhirn
              Mar 31 '16 at 11:23






            • 4





              Yes return is used for setting $? which is the exit status. In the above example, fun1's exit status would be 34. Also, note that $(...) also captures stderr in addition to stdout from command specified.

              – swoop81
              Nov 27 '17 at 21:33


















            • and return is a result code?

              – Blauhirn
              Mar 31 '16 at 11:23






            • 4





              Yes return is used for setting $? which is the exit status. In the above example, fun1's exit status would be 34. Also, note that $(...) also captures stderr in addition to stdout from command specified.

              – swoop81
              Nov 27 '17 at 21:33

















            and return is a result code?

            – Blauhirn
            Mar 31 '16 at 11:23





            and return is a result code?

            – Blauhirn
            Mar 31 '16 at 11:23




            4




            4





            Yes return is used for setting $? which is the exit status. In the above example, fun1's exit status would be 34. Also, note that $(...) also captures stderr in addition to stdout from command specified.

            – swoop81
            Nov 27 '17 at 21:33






            Yes return is used for setting $? which is the exit status. In the above example, fun1's exit status would be 34. Also, note that $(...) also captures stderr in addition to stdout from command specified.

            – swoop81
            Nov 27 '17 at 21:33












            42














            Functions in Bash are not functions like in other language; they're actually commands. So functions are used as if they were binaries or scripts fetched from your path. From the perspective of your program logic there should be really no difference.



            Shell commands are connected by pipes (aka streams), and not fundamental or user-defined data types, as in "real" programming languages. There is no such thing like a return value for a command, maybe mostly because there's no real way to declare it. It could occur on the man-page, or the --help output of the command, but both are only human-readable and hence are written to the wind.



            When a command wants to get input it reads it from its input stream, or the argument list. In both cases text strings have to be parsed.



            When a command wants to return something it has to echo it to its output stream. Another oftenly practiced way is to store the return value in dedicated, global variables. Writing to the output stream is clearer and more flexible, because it can take also binary data. For example, you can return a BLOB easily:



            encrypt() 
            gpg -c -o- $1 # encrypt data in filename to stdout (asks for a passphrase)


            encrypt public.dat > private.dat # write function result to file


            As others have written in this thread, the caller can also use command substitution $() to capture the output.



            Parallely, the function would "return" the exit code of gpg (GnuPG). Think of the exit code as a bonus that other languages don't have, or, depending on your temperament, as a "Schmutzeffekt" of shell functions. This status is, by convention, 0 on success or an integer in the range 1-255 for something else. To make this clear: return (like exit) can only take a value from 0-255, and values other than 0 are not necessarily errors, as is often asserted.



            When you don't provide an explicit value with return the status is taken from the last command in a Bash statement/function/command and so forth. So there is always a status, and return is just an easy way to provide it.






            share|improve this answer




















            • 1





              +1 for explaining functions vs commands and how this impacts the notion of sending data back to the caller

              – Oliver
              Aug 2 '18 at 22:16






            • 1





              +1 for explaining that shell programming is about connecting commands via pipes. Other programming languages compose functions via return types. Bash composes commands via streams of text.

              – jrahhali
              Nov 2 '18 at 0:10















            42














            Functions in Bash are not functions like in other language; they're actually commands. So functions are used as if they were binaries or scripts fetched from your path. From the perspective of your program logic there should be really no difference.



            Shell commands are connected by pipes (aka streams), and not fundamental or user-defined data types, as in "real" programming languages. There is no such thing like a return value for a command, maybe mostly because there's no real way to declare it. It could occur on the man-page, or the --help output of the command, but both are only human-readable and hence are written to the wind.



            When a command wants to get input it reads it from its input stream, or the argument list. In both cases text strings have to be parsed.



            When a command wants to return something it has to echo it to its output stream. Another oftenly practiced way is to store the return value in dedicated, global variables. Writing to the output stream is clearer and more flexible, because it can take also binary data. For example, you can return a BLOB easily:



            encrypt() 
            gpg -c -o- $1 # encrypt data in filename to stdout (asks for a passphrase)


            encrypt public.dat > private.dat # write function result to file


            As others have written in this thread, the caller can also use command substitution $() to capture the output.



            Parallely, the function would "return" the exit code of gpg (GnuPG). Think of the exit code as a bonus that other languages don't have, or, depending on your temperament, as a "Schmutzeffekt" of shell functions. This status is, by convention, 0 on success or an integer in the range 1-255 for something else. To make this clear: return (like exit) can only take a value from 0-255, and values other than 0 are not necessarily errors, as is often asserted.



            When you don't provide an explicit value with return the status is taken from the last command in a Bash statement/function/command and so forth. So there is always a status, and return is just an easy way to provide it.






            share|improve this answer




















            • 1





              +1 for explaining functions vs commands and how this impacts the notion of sending data back to the caller

              – Oliver
              Aug 2 '18 at 22:16






            • 1





              +1 for explaining that shell programming is about connecting commands via pipes. Other programming languages compose functions via return types. Bash composes commands via streams of text.

              – jrahhali
              Nov 2 '18 at 0:10













            42












            42








            42







            Functions in Bash are not functions like in other language; they're actually commands. So functions are used as if they were binaries or scripts fetched from your path. From the perspective of your program logic there should be really no difference.



            Shell commands are connected by pipes (aka streams), and not fundamental or user-defined data types, as in "real" programming languages. There is no such thing like a return value for a command, maybe mostly because there's no real way to declare it. It could occur on the man-page, or the --help output of the command, but both are only human-readable and hence are written to the wind.



            When a command wants to get input it reads it from its input stream, or the argument list. In both cases text strings have to be parsed.



            When a command wants to return something it has to echo it to its output stream. Another oftenly practiced way is to store the return value in dedicated, global variables. Writing to the output stream is clearer and more flexible, because it can take also binary data. For example, you can return a BLOB easily:



            encrypt() 
            gpg -c -o- $1 # encrypt data in filename to stdout (asks for a passphrase)


            encrypt public.dat > private.dat # write function result to file


            As others have written in this thread, the caller can also use command substitution $() to capture the output.



            Parallely, the function would "return" the exit code of gpg (GnuPG). Think of the exit code as a bonus that other languages don't have, or, depending on your temperament, as a "Schmutzeffekt" of shell functions. This status is, by convention, 0 on success or an integer in the range 1-255 for something else. To make this clear: return (like exit) can only take a value from 0-255, and values other than 0 are not necessarily errors, as is often asserted.



            When you don't provide an explicit value with return the status is taken from the last command in a Bash statement/function/command and so forth. So there is always a status, and return is just an easy way to provide it.






            share|improve this answer















            Functions in Bash are not functions like in other language; they're actually commands. So functions are used as if they were binaries or scripts fetched from your path. From the perspective of your program logic there should be really no difference.



            Shell commands are connected by pipes (aka streams), and not fundamental or user-defined data types, as in "real" programming languages. There is no such thing like a return value for a command, maybe mostly because there's no real way to declare it. It could occur on the man-page, or the --help output of the command, but both are only human-readable and hence are written to the wind.



            When a command wants to get input it reads it from its input stream, or the argument list. In both cases text strings have to be parsed.



            When a command wants to return something it has to echo it to its output stream. Another oftenly practiced way is to store the return value in dedicated, global variables. Writing to the output stream is clearer and more flexible, because it can take also binary data. For example, you can return a BLOB easily:



            encrypt() 
            gpg -c -o- $1 # encrypt data in filename to stdout (asks for a passphrase)


            encrypt public.dat > private.dat # write function result to file


            As others have written in this thread, the caller can also use command substitution $() to capture the output.



            Parallely, the function would "return" the exit code of gpg (GnuPG). Think of the exit code as a bonus that other languages don't have, or, depending on your temperament, as a "Schmutzeffekt" of shell functions. This status is, by convention, 0 on success or an integer in the range 1-255 for something else. To make this clear: return (like exit) can only take a value from 0-255, and values other than 0 are not necessarily errors, as is often asserted.



            When you don't provide an explicit value with return the status is taken from the last command in a Bash statement/function/command and so forth. So there is always a status, and return is just an easy way to provide it.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jun 27 '13 at 8:44

























            answered Jun 27 '13 at 8:31









            Andreas SpindlerAndreas Spindler

            4,51423230




            4,51423230







            • 1





              +1 for explaining functions vs commands and how this impacts the notion of sending data back to the caller

              – Oliver
              Aug 2 '18 at 22:16






            • 1





              +1 for explaining that shell programming is about connecting commands via pipes. Other programming languages compose functions via return types. Bash composes commands via streams of text.

              – jrahhali
              Nov 2 '18 at 0:10












            • 1





              +1 for explaining functions vs commands and how this impacts the notion of sending data back to the caller

              – Oliver
              Aug 2 '18 at 22:16






            • 1





              +1 for explaining that shell programming is about connecting commands via pipes. Other programming languages compose functions via return types. Bash composes commands via streams of text.

              – jrahhali
              Nov 2 '18 at 0:10







            1




            1





            +1 for explaining functions vs commands and how this impacts the notion of sending data back to the caller

            – Oliver
            Aug 2 '18 at 22:16





            +1 for explaining functions vs commands and how this impacts the notion of sending data back to the caller

            – Oliver
            Aug 2 '18 at 22:16




            1




            1





            +1 for explaining that shell programming is about connecting commands via pipes. Other programming languages compose functions via return types. Bash composes commands via streams of text.

            – jrahhali
            Nov 2 '18 at 0:10





            +1 for explaining that shell programming is about connecting commands via pipes. Other programming languages compose functions via return types. Bash composes commands via streams of text.

            – jrahhali
            Nov 2 '18 at 0:10











            23














            The return statement sets the exit code of the function, much the same as exit will do for the entire script.



            The exit code for the last command is always available in the $? variable.



            function fun1()
            return 34


            function fun2()
            local res=$(fun1)
            echo $? # <-- Always echos 0 since the 'local' command passes.

            res=$(fun1)
            echo $? #<-- Outputs 34






            share|improve this answer



























              23














              The return statement sets the exit code of the function, much the same as exit will do for the entire script.



              The exit code for the last command is always available in the $? variable.



              function fun1()
              return 34


              function fun2()
              local res=$(fun1)
              echo $? # <-- Always echos 0 since the 'local' command passes.

              res=$(fun1)
              echo $? #<-- Outputs 34






              share|improve this answer

























                23












                23








                23







                The return statement sets the exit code of the function, much the same as exit will do for the entire script.



                The exit code for the last command is always available in the $? variable.



                function fun1()
                return 34


                function fun2()
                local res=$(fun1)
                echo $? # <-- Always echos 0 since the 'local' command passes.

                res=$(fun1)
                echo $? #<-- Outputs 34






                share|improve this answer













                The return statement sets the exit code of the function, much the same as exit will do for the entire script.



                The exit code for the last command is always available in the $? variable.



                function fun1()
                return 34


                function fun2()
                local res=$(fun1)
                echo $? # <-- Always echos 0 since the 'local' command passes.

                res=$(fun1)
                echo $? #<-- Outputs 34







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jun 27 '13 at 7:25









                Austin PhillipsAustin Phillips

                11.5k13741




                11.5k13741





















                    5














                    I like to do the following if running in a script where the function is defined:



                    POINTER= # used for function return values

                    my_function()
                    # do stuff
                    POINTER="my_function_return"


                    my_other_function()
                    # do stuff
                    POINTER="my_other_function_return"


                    my_function
                    RESULT="$POINTER"

                    my_other_function
                    RESULT="$POINTER"


                    I like this, becase I can then include echo statements in my functions if I want



                    my_function() 
                    echo "-> my_function()"
                    # do stuff
                    POINTER="my_function_return"
                    echo "<- my_function. $POINTER"






                    share|improve this answer





























                      5














                      I like to do the following if running in a script where the function is defined:



                      POINTER= # used for function return values

                      my_function()
                      # do stuff
                      POINTER="my_function_return"


                      my_other_function()
                      # do stuff
                      POINTER="my_other_function_return"


                      my_function
                      RESULT="$POINTER"

                      my_other_function
                      RESULT="$POINTER"


                      I like this, becase I can then include echo statements in my functions if I want



                      my_function() 
                      echo "-> my_function()"
                      # do stuff
                      POINTER="my_function_return"
                      echo "<- my_function. $POINTER"






                      share|improve this answer



























                        5












                        5








                        5







                        I like to do the following if running in a script where the function is defined:



                        POINTER= # used for function return values

                        my_function()
                        # do stuff
                        POINTER="my_function_return"


                        my_other_function()
                        # do stuff
                        POINTER="my_other_function_return"


                        my_function
                        RESULT="$POINTER"

                        my_other_function
                        RESULT="$POINTER"


                        I like this, becase I can then include echo statements in my functions if I want



                        my_function() 
                        echo "-> my_function()"
                        # do stuff
                        POINTER="my_function_return"
                        echo "<- my_function. $POINTER"






                        share|improve this answer















                        I like to do the following if running in a script where the function is defined:



                        POINTER= # used for function return values

                        my_function()
                        # do stuff
                        POINTER="my_function_return"


                        my_other_function()
                        # do stuff
                        POINTER="my_other_function_return"


                        my_function
                        RESULT="$POINTER"

                        my_other_function
                        RESULT="$POINTER"


                        I like this, becase I can then include echo statements in my functions if I want



                        my_function() 
                        echo "-> my_function()"
                        # do stuff
                        POINTER="my_function_return"
                        echo "<- my_function. $POINTER"







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Jul 3 '15 at 12:02

























                        answered Jul 3 '15 at 11:21









                        docdoc

                        460411




                        460411





















                            4














                            Another way to achive this is name references (requires Bash 4.3+).



                            function example 
                            local -n VAR=$1
                            VAR=foo


                            example RESULT
                            echo $RESULT





                            share|improve this answer


















                            • 1





                              Wow I did not know about this, thanks for sharing.

                              – Oliver
                              Jan 18 at 18:23















                            4














                            Another way to achive this is name references (requires Bash 4.3+).



                            function example 
                            local -n VAR=$1
                            VAR=foo


                            example RESULT
                            echo $RESULT





                            share|improve this answer


















                            • 1





                              Wow I did not know about this, thanks for sharing.

                              – Oliver
                              Jan 18 at 18:23













                            4












                            4








                            4







                            Another way to achive this is name references (requires Bash 4.3+).



                            function example 
                            local -n VAR=$1
                            VAR=foo


                            example RESULT
                            echo $RESULT





                            share|improve this answer













                            Another way to achive this is name references (requires Bash 4.3+).



                            function example 
                            local -n VAR=$1
                            VAR=foo


                            example RESULT
                            echo $RESULT






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Oct 6 '18 at 10:48









                            ya.teckya.teck

                            9141528




                            9141528







                            • 1





                              Wow I did not know about this, thanks for sharing.

                              – Oliver
                              Jan 18 at 18:23












                            • 1





                              Wow I did not know about this, thanks for sharing.

                              – Oliver
                              Jan 18 at 18:23







                            1




                            1





                            Wow I did not know about this, thanks for sharing.

                            – Oliver
                            Jan 18 at 18:23





                            Wow I did not know about this, thanks for sharing.

                            – Oliver
                            Jan 18 at 18:23











                            4














                            The problem with other answers is they either use a global, which can be overwritten when several functions are in a call chain, or echo which means your function cannot output diagnostic info (you will forget your function does this and the "result", ie return value, will contain more info than your caller expects, leading to weird bug), or eval which is way heavy and hacky.



                            The proper way to do this is to put the top level stuff in a function and use a local with bash's dynamic scoping rule. Example:



                            func1() 

                            ret_val=hi


                            func2()

                            ret_val=bye


                            func3()

                            local ret_val=nothing
                            echo $ret_val
                            func1
                            echo $ret_val
                            func2
                            echo $ret_val


                            func3


                            This outputs



                            nothing
                            hi
                            bye


                            Dynamic scoping means that ret_val points to a different object depending on the caller! This is different from lexical scoping, which is what most programming languages use. This is actually a documented feature, just easy to miss, and not very well explained, here is the docs for it (emphasis is mine):




                            Variables local to the function may be declared with the local
                            builtin. These variables are visible only to the function and the
                            commands it invokes
                            .




                            For someone with a C/C++/Python/Java/C#/javascript background, this is probably the biggest hurdle: functions in bash are not functions, they are commands, and behave as such: they can output to stdout/stderr, they can pipe in/out, they can return an exit code. Basically there is no difference between defining a command in a script and creating an executable that can be called from the command.



                            So instead of writing your script like this:



                            top-level code 
                            bunch of functions
                            more top-level code


                            write it like this:



                            # define your main, containing all top-level code
                            main()
                            bunch of functions
                            # call main
                            main


                            where main() declares ret_val as local and all other functions return values via ret_val.



                            See also https://unix.stackexchange.com/questions/282557/scope-of-local-variables-in-shell-functions.



                            Another, perhaps even better solution depending on situation, is the one posted by ya.teck which uses local -n.






                            share|improve this answer





























                              4














                              The problem with other answers is they either use a global, which can be overwritten when several functions are in a call chain, or echo which means your function cannot output diagnostic info (you will forget your function does this and the "result", ie return value, will contain more info than your caller expects, leading to weird bug), or eval which is way heavy and hacky.



                              The proper way to do this is to put the top level stuff in a function and use a local with bash's dynamic scoping rule. Example:



                              func1() 

                              ret_val=hi


                              func2()

                              ret_val=bye


                              func3()

                              local ret_val=nothing
                              echo $ret_val
                              func1
                              echo $ret_val
                              func2
                              echo $ret_val


                              func3


                              This outputs



                              nothing
                              hi
                              bye


                              Dynamic scoping means that ret_val points to a different object depending on the caller! This is different from lexical scoping, which is what most programming languages use. This is actually a documented feature, just easy to miss, and not very well explained, here is the docs for it (emphasis is mine):




                              Variables local to the function may be declared with the local
                              builtin. These variables are visible only to the function and the
                              commands it invokes
                              .




                              For someone with a C/C++/Python/Java/C#/javascript background, this is probably the biggest hurdle: functions in bash are not functions, they are commands, and behave as such: they can output to stdout/stderr, they can pipe in/out, they can return an exit code. Basically there is no difference between defining a command in a script and creating an executable that can be called from the command.



                              So instead of writing your script like this:



                              top-level code 
                              bunch of functions
                              more top-level code


                              write it like this:



                              # define your main, containing all top-level code
                              main()
                              bunch of functions
                              # call main
                              main


                              where main() declares ret_val as local and all other functions return values via ret_val.



                              See also https://unix.stackexchange.com/questions/282557/scope-of-local-variables-in-shell-functions.



                              Another, perhaps even better solution depending on situation, is the one posted by ya.teck which uses local -n.






                              share|improve this answer



























                                4












                                4








                                4







                                The problem with other answers is they either use a global, which can be overwritten when several functions are in a call chain, or echo which means your function cannot output diagnostic info (you will forget your function does this and the "result", ie return value, will contain more info than your caller expects, leading to weird bug), or eval which is way heavy and hacky.



                                The proper way to do this is to put the top level stuff in a function and use a local with bash's dynamic scoping rule. Example:



                                func1() 

                                ret_val=hi


                                func2()

                                ret_val=bye


                                func3()

                                local ret_val=nothing
                                echo $ret_val
                                func1
                                echo $ret_val
                                func2
                                echo $ret_val


                                func3


                                This outputs



                                nothing
                                hi
                                bye


                                Dynamic scoping means that ret_val points to a different object depending on the caller! This is different from lexical scoping, which is what most programming languages use. This is actually a documented feature, just easy to miss, and not very well explained, here is the docs for it (emphasis is mine):




                                Variables local to the function may be declared with the local
                                builtin. These variables are visible only to the function and the
                                commands it invokes
                                .




                                For someone with a C/C++/Python/Java/C#/javascript background, this is probably the biggest hurdle: functions in bash are not functions, they are commands, and behave as such: they can output to stdout/stderr, they can pipe in/out, they can return an exit code. Basically there is no difference between defining a command in a script and creating an executable that can be called from the command.



                                So instead of writing your script like this:



                                top-level code 
                                bunch of functions
                                more top-level code


                                write it like this:



                                # define your main, containing all top-level code
                                main()
                                bunch of functions
                                # call main
                                main


                                where main() declares ret_val as local and all other functions return values via ret_val.



                                See also https://unix.stackexchange.com/questions/282557/scope-of-local-variables-in-shell-functions.



                                Another, perhaps even better solution depending on situation, is the one posted by ya.teck which uses local -n.






                                share|improve this answer















                                The problem with other answers is they either use a global, which can be overwritten when several functions are in a call chain, or echo which means your function cannot output diagnostic info (you will forget your function does this and the "result", ie return value, will contain more info than your caller expects, leading to weird bug), or eval which is way heavy and hacky.



                                The proper way to do this is to put the top level stuff in a function and use a local with bash's dynamic scoping rule. Example:



                                func1() 

                                ret_val=hi


                                func2()

                                ret_val=bye


                                func3()

                                local ret_val=nothing
                                echo $ret_val
                                func1
                                echo $ret_val
                                func2
                                echo $ret_val


                                func3


                                This outputs



                                nothing
                                hi
                                bye


                                Dynamic scoping means that ret_val points to a different object depending on the caller! This is different from lexical scoping, which is what most programming languages use. This is actually a documented feature, just easy to miss, and not very well explained, here is the docs for it (emphasis is mine):




                                Variables local to the function may be declared with the local
                                builtin. These variables are visible only to the function and the
                                commands it invokes
                                .




                                For someone with a C/C++/Python/Java/C#/javascript background, this is probably the biggest hurdle: functions in bash are not functions, they are commands, and behave as such: they can output to stdout/stderr, they can pipe in/out, they can return an exit code. Basically there is no difference between defining a command in a script and creating an executable that can be called from the command.



                                So instead of writing your script like this:



                                top-level code 
                                bunch of functions
                                more top-level code


                                write it like this:



                                # define your main, containing all top-level code
                                main()
                                bunch of functions
                                # call main
                                main


                                where main() declares ret_val as local and all other functions return values via ret_val.



                                See also https://unix.stackexchange.com/questions/282557/scope-of-local-variables-in-shell-functions.



                                Another, perhaps even better solution depending on situation, is the one posted by ya.teck which uses local -n.







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Mar 22 at 18:05

























                                answered Aug 29 '18 at 16:26









                                OliverOliver

                                16k32547




                                16k32547





















                                    3














                                    As an add-on to others' excellent posts, here's an article summarizing these techniques:



                                    • set a global variable

                                    • set a global variable, whose name you passed to the function

                                    • set the return code (and pick it up with $?)

                                    • 'echo' some data (and pick it up with MYVAR=$(myfunction) )

                                    Returning Values from Bash Functions






                                    share|improve this answer



























                                      3














                                      As an add-on to others' excellent posts, here's an article summarizing these techniques:



                                      • set a global variable

                                      • set a global variable, whose name you passed to the function

                                      • set the return code (and pick it up with $?)

                                      • 'echo' some data (and pick it up with MYVAR=$(myfunction) )

                                      Returning Values from Bash Functions






                                      share|improve this answer

























                                        3












                                        3








                                        3







                                        As an add-on to others' excellent posts, here's an article summarizing these techniques:



                                        • set a global variable

                                        • set a global variable, whose name you passed to the function

                                        • set the return code (and pick it up with $?)

                                        • 'echo' some data (and pick it up with MYVAR=$(myfunction) )

                                        Returning Values from Bash Functions






                                        share|improve this answer













                                        As an add-on to others' excellent posts, here's an article summarizing these techniques:



                                        • set a global variable

                                        • set a global variable, whose name you passed to the function

                                        • set the return code (and pick it up with $?)

                                        • 'echo' some data (and pick it up with MYVAR=$(myfunction) )

                                        Returning Values from Bash Functions







                                        share|improve this answer












                                        share|improve this answer



                                        share|improve this answer










                                        answered Jul 30 '18 at 21:04









                                        Tom HundtTom Hundt

                                        763913




                                        763913





















                                            -2














                                            Git Bash on Windows using arrays for multiple return values



                                            BASH CODE:



                                            #!/bin/bash

                                            ##A 6-element array used for returning
                                            ##values from functions:
                                            declare -a RET_ARR
                                            RET_ARR[0]="A"
                                            RET_ARR[1]="B"
                                            RET_ARR[2]="C"
                                            RET_ARR[3]="D"
                                            RET_ARR[4]="E"
                                            RET_ARR[5]="F"


                                            function FN_MULTIPLE_RETURN_VALUES()

                                            ##give the positional arguments/inputs
                                            ##$1 and $2 some sensible names:
                                            local out_dex_1="$1" ##output index
                                            local out_dex_2="$2" ##output index

                                            ##Echo for debugging:
                                            echo "running: FN_MULTIPLE_RETURN_VALUES"

                                            ##Here: Calculate output values:
                                            local op_var_1="Hello"
                                            local op_var_2="World"

                                            ##set the return values:
                                            RET_ARR[ $out_dex_1 ]=$op_var_1
                                            RET_ARR[ $out_dex_2 ]=$op_var_2



                                            echo "FN_MULTIPLE_RETURN_VALUES EXAMPLES:"
                                            echo "-------------------------------------------"
                                            fn="FN_MULTIPLE_RETURN_VALUES"
                                            out_dex_a=0
                                            out_dex_b=1
                                            eval $fn $out_dex_a $out_dex_b ##<--Call function
                                            a=$RET_ARR[0] && echo "RET_ARR[0]: $a "
                                            b=$RET_ARR[1] && echo "RET_ARR[1]: $b "
                                            echo
                                            ##----------------------------------------------##
                                            c="2"
                                            d="3"
                                            FN_MULTIPLE_RETURN_VALUES $c $d ##<--Call function
                                            c_res=$RET_ARR[2] && echo "RET_ARR[2]: $c_res "
                                            d_res=$RET_ARR[3] && echo "RET_ARR[3]: $d_res "
                                            echo
                                            ##----------------------------------------------##
                                            FN_MULTIPLE_RETURN_VALUES 4 5 ##<---Call function
                                            e=$RET_ARR[4] && echo "RET_ARR[4]: $e "
                                            f=$RET_ARR[5] && echo "RET_ARR[5]: $f "
                                            echo
                                            ##----------------------------------------------##


                                            read -p "Press Enter To Exit:"


                                            EXPECTED OUTPUT:



                                            FN_MULTIPLE_RETURN_VALUES EXAMPLES:
                                            -------------------------------------------
                                            running: FN_MULTIPLE_RETURN_VALUES
                                            RET_ARR[0]: Hello
                                            RET_ARR[1]: World

                                            running: FN_MULTIPLE_RETURN_VALUES
                                            RET_ARR[2]: Hello
                                            RET_ARR[3]: World

                                            running: FN_MULTIPLE_RETURN_VALUES
                                            RET_ARR[4]: Hello
                                            RET_ARR[5]: World

                                            Press Enter To Exit:





                                            share|improve this answer



























                                              -2














                                              Git Bash on Windows using arrays for multiple return values



                                              BASH CODE:



                                              #!/bin/bash

                                              ##A 6-element array used for returning
                                              ##values from functions:
                                              declare -a RET_ARR
                                              RET_ARR[0]="A"
                                              RET_ARR[1]="B"
                                              RET_ARR[2]="C"
                                              RET_ARR[3]="D"
                                              RET_ARR[4]="E"
                                              RET_ARR[5]="F"


                                              function FN_MULTIPLE_RETURN_VALUES()

                                              ##give the positional arguments/inputs
                                              ##$1 and $2 some sensible names:
                                              local out_dex_1="$1" ##output index
                                              local out_dex_2="$2" ##output index

                                              ##Echo for debugging:
                                              echo "running: FN_MULTIPLE_RETURN_VALUES"

                                              ##Here: Calculate output values:
                                              local op_var_1="Hello"
                                              local op_var_2="World"

                                              ##set the return values:
                                              RET_ARR[ $out_dex_1 ]=$op_var_1
                                              RET_ARR[ $out_dex_2 ]=$op_var_2



                                              echo "FN_MULTIPLE_RETURN_VALUES EXAMPLES:"
                                              echo "-------------------------------------------"
                                              fn="FN_MULTIPLE_RETURN_VALUES"
                                              out_dex_a=0
                                              out_dex_b=1
                                              eval $fn $out_dex_a $out_dex_b ##<--Call function
                                              a=$RET_ARR[0] && echo "RET_ARR[0]: $a "
                                              b=$RET_ARR[1] && echo "RET_ARR[1]: $b "
                                              echo
                                              ##----------------------------------------------##
                                              c="2"
                                              d="3"
                                              FN_MULTIPLE_RETURN_VALUES $c $d ##<--Call function
                                              c_res=$RET_ARR[2] && echo "RET_ARR[2]: $c_res "
                                              d_res=$RET_ARR[3] && echo "RET_ARR[3]: $d_res "
                                              echo
                                              ##----------------------------------------------##
                                              FN_MULTIPLE_RETURN_VALUES 4 5 ##<---Call function
                                              e=$RET_ARR[4] && echo "RET_ARR[4]: $e "
                                              f=$RET_ARR[5] && echo "RET_ARR[5]: $f "
                                              echo
                                              ##----------------------------------------------##


                                              read -p "Press Enter To Exit:"


                                              EXPECTED OUTPUT:



                                              FN_MULTIPLE_RETURN_VALUES EXAMPLES:
                                              -------------------------------------------
                                              running: FN_MULTIPLE_RETURN_VALUES
                                              RET_ARR[0]: Hello
                                              RET_ARR[1]: World

                                              running: FN_MULTIPLE_RETURN_VALUES
                                              RET_ARR[2]: Hello
                                              RET_ARR[3]: World

                                              running: FN_MULTIPLE_RETURN_VALUES
                                              RET_ARR[4]: Hello
                                              RET_ARR[5]: World

                                              Press Enter To Exit:





                                              share|improve this answer

























                                                -2












                                                -2








                                                -2







                                                Git Bash on Windows using arrays for multiple return values



                                                BASH CODE:



                                                #!/bin/bash

                                                ##A 6-element array used for returning
                                                ##values from functions:
                                                declare -a RET_ARR
                                                RET_ARR[0]="A"
                                                RET_ARR[1]="B"
                                                RET_ARR[2]="C"
                                                RET_ARR[3]="D"
                                                RET_ARR[4]="E"
                                                RET_ARR[5]="F"


                                                function FN_MULTIPLE_RETURN_VALUES()

                                                ##give the positional arguments/inputs
                                                ##$1 and $2 some sensible names:
                                                local out_dex_1="$1" ##output index
                                                local out_dex_2="$2" ##output index

                                                ##Echo for debugging:
                                                echo "running: FN_MULTIPLE_RETURN_VALUES"

                                                ##Here: Calculate output values:
                                                local op_var_1="Hello"
                                                local op_var_2="World"

                                                ##set the return values:
                                                RET_ARR[ $out_dex_1 ]=$op_var_1
                                                RET_ARR[ $out_dex_2 ]=$op_var_2



                                                echo "FN_MULTIPLE_RETURN_VALUES EXAMPLES:"
                                                echo "-------------------------------------------"
                                                fn="FN_MULTIPLE_RETURN_VALUES"
                                                out_dex_a=0
                                                out_dex_b=1
                                                eval $fn $out_dex_a $out_dex_b ##<--Call function
                                                a=$RET_ARR[0] && echo "RET_ARR[0]: $a "
                                                b=$RET_ARR[1] && echo "RET_ARR[1]: $b "
                                                echo
                                                ##----------------------------------------------##
                                                c="2"
                                                d="3"
                                                FN_MULTIPLE_RETURN_VALUES $c $d ##<--Call function
                                                c_res=$RET_ARR[2] && echo "RET_ARR[2]: $c_res "
                                                d_res=$RET_ARR[3] && echo "RET_ARR[3]: $d_res "
                                                echo
                                                ##----------------------------------------------##
                                                FN_MULTIPLE_RETURN_VALUES 4 5 ##<---Call function
                                                e=$RET_ARR[4] && echo "RET_ARR[4]: $e "
                                                f=$RET_ARR[5] && echo "RET_ARR[5]: $f "
                                                echo
                                                ##----------------------------------------------##


                                                read -p "Press Enter To Exit:"


                                                EXPECTED OUTPUT:



                                                FN_MULTIPLE_RETURN_VALUES EXAMPLES:
                                                -------------------------------------------
                                                running: FN_MULTIPLE_RETURN_VALUES
                                                RET_ARR[0]: Hello
                                                RET_ARR[1]: World

                                                running: FN_MULTIPLE_RETURN_VALUES
                                                RET_ARR[2]: Hello
                                                RET_ARR[3]: World

                                                running: FN_MULTIPLE_RETURN_VALUES
                                                RET_ARR[4]: Hello
                                                RET_ARR[5]: World

                                                Press Enter To Exit:





                                                share|improve this answer













                                                Git Bash on Windows using arrays for multiple return values



                                                BASH CODE:



                                                #!/bin/bash

                                                ##A 6-element array used for returning
                                                ##values from functions:
                                                declare -a RET_ARR
                                                RET_ARR[0]="A"
                                                RET_ARR[1]="B"
                                                RET_ARR[2]="C"
                                                RET_ARR[3]="D"
                                                RET_ARR[4]="E"
                                                RET_ARR[5]="F"


                                                function FN_MULTIPLE_RETURN_VALUES()

                                                ##give the positional arguments/inputs
                                                ##$1 and $2 some sensible names:
                                                local out_dex_1="$1" ##output index
                                                local out_dex_2="$2" ##output index

                                                ##Echo for debugging:
                                                echo "running: FN_MULTIPLE_RETURN_VALUES"

                                                ##Here: Calculate output values:
                                                local op_var_1="Hello"
                                                local op_var_2="World"

                                                ##set the return values:
                                                RET_ARR[ $out_dex_1 ]=$op_var_1
                                                RET_ARR[ $out_dex_2 ]=$op_var_2



                                                echo "FN_MULTIPLE_RETURN_VALUES EXAMPLES:"
                                                echo "-------------------------------------------"
                                                fn="FN_MULTIPLE_RETURN_VALUES"
                                                out_dex_a=0
                                                out_dex_b=1
                                                eval $fn $out_dex_a $out_dex_b ##<--Call function
                                                a=$RET_ARR[0] && echo "RET_ARR[0]: $a "
                                                b=$RET_ARR[1] && echo "RET_ARR[1]: $b "
                                                echo
                                                ##----------------------------------------------##
                                                c="2"
                                                d="3"
                                                FN_MULTIPLE_RETURN_VALUES $c $d ##<--Call function
                                                c_res=$RET_ARR[2] && echo "RET_ARR[2]: $c_res "
                                                d_res=$RET_ARR[3] && echo "RET_ARR[3]: $d_res "
                                                echo
                                                ##----------------------------------------------##
                                                FN_MULTIPLE_RETURN_VALUES 4 5 ##<---Call function
                                                e=$RET_ARR[4] && echo "RET_ARR[4]: $e "
                                                f=$RET_ARR[5] && echo "RET_ARR[5]: $f "
                                                echo
                                                ##----------------------------------------------##


                                                read -p "Press Enter To Exit:"


                                                EXPECTED OUTPUT:



                                                FN_MULTIPLE_RETURN_VALUES EXAMPLES:
                                                -------------------------------------------
                                                running: FN_MULTIPLE_RETURN_VALUES
                                                RET_ARR[0]: Hello
                                                RET_ARR[1]: World

                                                running: FN_MULTIPLE_RETURN_VALUES
                                                RET_ARR[2]: Hello
                                                RET_ARR[3]: World

                                                running: FN_MULTIPLE_RETURN_VALUES
                                                RET_ARR[4]: Hello
                                                RET_ARR[5]: World

                                                Press Enter To Exit:






                                                share|improve this answer












                                                share|improve this answer



                                                share|improve this answer










                                                answered Sep 13 '17 at 15:17









                                                J.M.I. MADISONJ.M.I. MADISON

                                                1,344129




                                                1,344129















                                                    protected by codeforester Aug 29 '18 at 16:54



                                                    Thank you for your interest in this question.
                                                    Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                                                    Would you like to answer one of these unanswered questions instead?



                                                    Popular posts from this blog

                                                    Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

                                                    Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

                                                    Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript