# Returning an exit code from a bash function

**URL:** <https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621>\
**Category:** Shell Programming and Scripting\
**Created:** [January 19, 2017, 11:22pm UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621 "2017-01-19T23:22:48Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![wolfv](https://community.unix.com/letter_avatar/wolfv/32/5_5575768a8748004e209b776fc1b2916d.png) [@wolfv](https://community.unix.com/u/wolfv)\
**Post date:** [January 19, 2017, 11:22pm UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/1 "2017-01-19T23:22:48Z")

</div>

How to return a exit code from a function and use it in conditional?  
I tried the following but it does not seem to work.

tests.sh:

```nohighlight
if test ./load.sh ; then
    echo "0"
else
    echo "1"
fi

```

load.sh:

```nohighlight
return 1;

```

from command line:

```nohighlight
$ ./tests.sh
0

```

I was expecting it to output "1" 😕  
Thank you.

---

<div class="post-metadata">

**Author:** ![jim\_mcnamara](https://community.unix.com/letter_avatar/jim_mcnamara/32/5_5575768a8748004e209b776fc1b2916d.png) [@jim\_mcnamara](https://community.unix.com/u/jim_mcnamara)\
**Post date:** [January 19, 2017, 11:33pm UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/2 "2017-01-19T23:33:50Z")

</div>

I'm confused. The `return 1` statement can only be used in a function or a sourced shell script. This doesn't apply here?

Are you sure you are using bash for this? If you do not specify:

```nohighlight
#!/bin/bash

```

as the very first line of test.sh then you are using

```nohighlight
/bin/sh

```

which is a POSIX shell, not necessarily bash.

```nohighlight
 echo $SHELL

```

will tell you ( inside test.sh) what shell you are using.

So help us to help you with some more information.

PLUS  
a return code of zero means success in the shell, any other number is a fail.

---

<div class="post-metadata">

**Author:** ![jim\_mcnamara](https://community.unix.com/letter_avatar/jim_mcnamara/32/5_5575768a8748004e209b776fc1b2916d.png) [@jim\_mcnamara](https://community.unix.com/u/jim_mcnamara)\
**Post date:** [January 19, 2017, 11:38pm UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/3 "2017-01-19T23:38:32Z")

</div>

PS: this is what I get for test.sh and my system

```nohighlight
Owner@Owner-PC ~
$ chmod +x test.sh

Owner@Owner-PC ~
$ ./test.sh
./test.sh: line 2: return: can only `return' from a function or sourced script

Owner@Owner-PC ~
$ bash --version
GNU bash, version 4.4.5(1)-release (x86_64-unknown-cygwin)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

```

I do not want to boot to linux && have to shutdown my windows stuff right now - so cygwin.

---

<div class="post-metadata">

**Author:** ![wolfv](https://community.unix.com/letter_avatar/wolfv/32/5_5575768a8748004e209b776fc1b2916d.png) [@wolfv](https://community.unix.com/u/wolfv)\
**Post date:** [January 20, 2017, 12:27am UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/4 "2017-01-20T00:27:44Z")

</div>

> [@jim mcnamara](#):
>
> I'm confused. The `return 1` statement can only be used in a function or a sourced shell script. This doesn't apply here?

Sorry I left out the bash header. I am using Bash.

I have several load.sh scripts, and want to call them all from one test.sh script.  
Each load.sh script calls a C++ function that returns an error code (0 means EXIT\_SUCCESS).  
Is there a way to pass the error code from C++ function, to load.sh, to test.sh?  
And then test.sh use the returned error code in a conditional statement?

Thanks.

tests.sh:

```plaintext
#!/bin/bash

if test ./load.sh ; then
    echo "0"
else
    echo "1"
fi

```

load.sh:

```plaintext
#!/bin/bash

return main

```

```plaintext
int main()
{
    return 1; //1 means EXIT_FAILURE
}

```

from command line:

```plaintext
$ g++ main.cpp -o main
$ ./tests.sh
0

```

I was expecting it to output "1".

---

<div class="post-metadata">

**Author:** ![Don\_Cragun](https://community.unix.com/user_avatar/community.unix.com/don_cragun/32/2682_2.png) [@Don\_Cragun](https://community.unix.com/u/Don_Cragun)\
**Post date:** [January 20, 2017, 1:30am UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/5 "2017-01-20T01:30:41Z")

</div>

The `bash` shell script:

```nohighlight
#!/bin/bash

return main

```

does not make any attempt to run the utility named `main` . And, as jim mcnamara already said, you don't use `return` to exit from a `bash` shell script. According to the standards, using `return` when you are not inside a function or inside a script invoked by the `.` command produces unspecified results. Running that script with `bash` prints two diagnostic messages:

```nohighlight
load.sh: line 2: return: main: numeric argument required
load.sh: line 2: return: can only `return' from a function or sourced script

```

and exits with exit code 1. Running that same script with `ksh` produces no diagnostics and exits with exit code 0.

If you just want a shell script that invokes a utility named `main` and exits with an exit code matching that returned by `main` , you can use any of the following:

```nohighlight
#!/bin/bash
main
rc=$?
if [$rc -eq 0]
then	exit 0
else	exit $rc
fi

```

or:

```nohighlight
#!/bin/bash
main
rc=$?
if [$rc -eq 0]
then	exit 0
fi
exit $rc

```

or:

```nohighlight
#!/bin/bash
main
rc=$?
exit $rc

```

or:

```nohighlight
#!/bin/bash
main
exit $?

```

or, more simply, just:

```nohighlight
#!/bin/bash
main

```

---

<div class="post-metadata">

**Author:** ![wolfv](https://community.unix.com/letter_avatar/wolfv/32/5_5575768a8748004e209b776fc1b2916d.png) [@wolfv](https://community.unix.com/u/wolfv)\
**Post date:** [January 20, 2017, 2:20am UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/6 "2017-01-20T02:20:39Z")

</div>

Thanks Don Cragun.

I tried the scripts you suggested in my load.sh file, but get the same result.

load.sh:

```nohighlight
#!/bin/bash
main
rc=$?
exit $rc

```

From command line:

```nohighlight
$ ./tests.sh
0

```

Bash is not giving may any messages when I run tests.sh. Yet jim mcnamara and you are seeing messages.  
Is that something I can turn on?

However, I do get a message when I run load.sh directly:

```nohighlight
$ ./load.sh
./load.sh: line 2: main: command not found
127
$ ls
load.sh load.sh~ main main.cpp main.cpp~ tests.sh tests.sh~

```

---------- Post updated at 03:20 AM ---------- Previous update was at 03:15 AM ----------

Update:

Adding "./" to load.sh fixed load.sh:

```nohighlight
#!/bin/bash
./main
rc=$?
echo $rc
exit $rc

```

From terminal:

```nohighlight
$ ./load.sh
1

```

But tests.sh still prints 0:

```nohighlight
$ ./tests.sh
0

```

I was expecting it to output "1".

---

<div class="post-metadata">

**Author:** ![Scrutinizer](https://community.unix.com/user_avatar/community.unix.com/scrutinizer/32/1216_2.png) [@Scrutinizer](https://community.unix.com/u/Scrutinizer)\
**Post date:** [January 20, 2017, 2:42am UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/7 "2017-01-20T02:42:22Z")

</div>

Try:

```plaintext
if ./load.sh ; then
    echo "0"
else
    echo "1"
fi

```

--  
See [test: operands](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html#tag_20_128_05)

```plaintext
string
True if the string string is not the null string; otherwise, false.

```

---

<div class="post-metadata">

**Author:** ![rovf](https://community.unix.com/letter_avatar/rovf/32/5_5575768a8748004e209b776fc1b2916d.png) [@rovf](https://community.unix.com/u/rovf)\
**Post date:** [January 20, 2017, 2:49am UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/8 "2017-01-20T02:49:51Z")

</div>

> [@wolfv](#):
>
> How to return a exit code from a function and use it in conditional?

I don't see any function in the code you have posted ....

---

<div class="post-metadata">

**Author:** ![wolfv](https://community.unix.com/letter_avatar/wolfv/32/5_5575768a8748004e209b776fc1b2916d.png) [@wolfv](https://community.unix.com/u/wolfv)\
**Post date:** [January 20, 2017, 3:49am UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/9 "2017-01-20T03:49:12Z")

</div>

Thank you Scrutinizer, that worked. Outputs are as expected!

test.sh:

```nohighlight
#!/bin/bash
if ./load.sh
then
    echo "0"
else
    echo "1"
fi

```

load.sh:

```nohighlight
#!/bin/bash
main
rc=$?
echo $rc
exit $rc

```

main.cpp:

```nohighlight
int main()
{
    return 1; //EXIT_FAILURE
}

```

From terminal:

```nohighlight
$ ./tests.sh
1
1

```

Also works with load.sh like this:

```nohighlight
#!/bin/bash
./main

```

---------- Post updated at 04:49 AM ---------- Previous update was at 04:01 AM ----------

It stopped working after changing the location of the load.sh file:

$ cat tests.sh

```nohighlight
#!/bin/bash
if test ../tut0/load.sh
then
    echo "0"
else
    echo "1"
fi

```

$ cat ../tut0/load.sh

```nohighlight
#!/bin/bash
./main
rc=$?
echo $rc
exit $rc

```

$ cat ../tut0/main.cpp

```nohighlight
int main()
{
    return 1; //EXIT_FAILURE
}
$ ls ../tut0
load.sh main main.cpp

```

Bash is not warning that the load.sh file was not found.  
Is there a way to make Bash throw an error when a file is not found?

What is the proper way to specify a relative path in bash?

Thank you.

---

<div class="post-metadata">

**Author:** ![rovf](https://community.unix.com/letter_avatar/rovf/32/5_5575768a8748004e209b776fc1b2916d.png) [@rovf](https://community.unix.com/u/rovf)\
**Post date:** [January 20, 2017, 8:24am UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/10 "2017-01-20T08:24:51Z")

</div>

In your modified example, I don't see that you would execute load.sh anywhere. What effect would you like to see? Please provide a complete transscript, showing what you are doing.

---

<div class="post-metadata">

**Author:** ![wolfv](https://community.unix.com/letter_avatar/wolfv/32/5_5575768a8748004e209b776fc1b2916d.png) [@wolfv](https://community.unix.com/u/wolfv)\
**Post date:** [January 20, 2017, 12:12pm UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/11 "2017-01-20T12:12:23Z")

</div>

> [@rovf](#):
>
> In your modified example, I don't see that you would execute load.sh anywhere. What effect would you like to see? Please provide a complete transscript, showing what you are doing.

The example in post #9 works, it has all the files in one directory.  
A C++ function main(), returns an error code (1 means EXIT\_FAILURE).  
The error code is passed from the main() function, to load.sh, to test.sh.  
And then test.sh uses the returned error code in a conditional statement.

The following example is similar, but with load.sh script in a different directory.  
The files where copied from the example in post #9, and the relative paths updated.  
But the output is not as expected, and Bash is not printing any error messages.

The following is a listing of the files with the new relative paths, followed by output.

$ cat tests.sh with new relative path:

```plaintext
#!/bin/bash
if test ../tut0/load.sh
then
    echo "0"
else
    echo "1"
fi

```

$ cat ../tut0/load.sh with new relative path:

```plaintext
#!/bin/bash
../suite/main
rc=$?
echo $rc
exit $rc

```

$ cat main.cpp:

```plaintext
int main()
{
    return 1; //EXIT_FAILURE
}

```

From the terminal:

```plaintext
$ g++ main.cpp -o main
$ ./tests.sh
0

```

I was expecting it to output "1" twice, as in post #9.

A top view of the directory structure:

```plaintext
$ cd ..
$ ls 
suite tut0 tut1
$ ls suite
load.sh main main.cpp~ tests.sh
load.sh~ main.cpp tests.sh~
$ ls tut0
load.sh load.sh~

```

What is the proper way to specify a relative path in bash?

Thank you.

---

<div class="post-metadata">

**Author:** ![RudiC](https://community.unix.com/letter_avatar/rudic/32/5_5575768a8748004e209b776fc1b2916d.png) [@RudiC](https://community.unix.com/u/RudiC)\
**Post date:** [January 20, 2017, 12:48pm UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/12 "2017-01-20T12:48:13Z")

</div>

For debug purposes, you might want to `pwd` in each and every script, and also `ls` the relevant paths/scripts.

---

<div class="post-metadata">

**Author:** ![wolfv](https://community.unix.com/letter_avatar/wolfv/32/5_5575768a8748004e209b776fc1b2916d.png) [@wolfv](https://community.unix.com/u/wolfv)\
**Post date:** [January 20, 2017, 1:40pm UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/13 "2017-01-20T13:40:24Z")

</div>

> [@rudic](#):
>
> For debug purposes, you might want to `pwd` in each and every script, and also `ls` the relevant paths/scripts.

Good idea. The pwd and ls outputs are as expected. But load.sh never gets called.  
Why is load.sh not called?

$ cat tests.sh

```plaintext
#!/bin/bash
echo "in tests.sh --------"
echo "pwd:"
pwd
echo "ls:"
ls
echo "ls ../tut0:"
ls ../tut0

echo "load.sh returned:"
if test ../tut0/load.sh
then
    echo "0"
else
    echo "1"
fi

```

$ cat ../tut0/load.sh

```plaintext
#!/bin/bash
echo "in load.sh --------"
echo "pwd:"
pwd
echo "ls:"
ls
ls "ls ../suite:"
ls ../suite

../suite/main
rc=$?
echo "rc:"
echo $rc
exit $rc

```

From the terminal:

```plaintext
$ ./tests.sh
in tests.sh --------
pwd:
/home/wolfv/Documents/developer/c++/demo/test_script/suite
ls:
load.sh load.sh~ main main.cpp main.cpp~ tests.sh	tests.sh~
ls ../tut0:
load.sh load.sh~
load.sh returned:
0

```

I was expecting output to also contain the line "in load.sh --------".

---

<div class="post-metadata">

**Author:** ![RudiC](https://community.unix.com/letter_avatar/rudic/32/5_5575768a8748004e209b776fc1b2916d.png) [@RudiC](https://community.unix.com/u/RudiC)\
**Post date:** [January 20, 2017, 2:35pm UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/14 "2017-01-20T14:35:51Z")

</div>

What if you run `../tut0/load.sh` without `test` ? And, how about setting `bash` 's xtrace option?

---

<div class="post-metadata">

**Author:** ![wolfv](https://community.unix.com/letter_avatar/wolfv/32/5_5575768a8748004e209b776fc1b2916d.png) [@wolfv](https://community.unix.com/u/wolfv)\
**Post date:** [January 20, 2017, 3:43pm UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/15 "2017-01-20T15:43:51Z")

</div>

> [@rudic](#):
>
> What if you run `../tut0/load.sh` without `test` ? And, how about setting `bash` 's xtrace option?

I didn't know about xtrace. Nice. Thanks for the tip.  
Running `../tut0/load.sh` directly works fine.  
But `test.sh` is not calling `../tut0/load.sh` .

$ cat tests.sh

```plaintext
#!/bin/bash
echo "in tests.sh --------"
pwd
ls
ls ../tut0

if test ../tut0/load.sh
then
    echo "0"
else
    echo "1"
fi

```

$ cat ../tut0/load.sh

```plaintext
#!/bin/bash
echo "in load.sh --------"
pwd
ls
ls ../suite

../suite/main
rc=$?

```

From the terminal:

```plaintext
$ bash -x ./tests.sh
+ echo 'in tests.sh --------'
in tests.sh --------
+ pwd
/home/wolfv/Documents/developer/c++/demo/test_script/suite
+ ls
load.sh load.sh~ main main.cpp main.cpp~ tests.sh	tests.sh~
+ ls ../tut0
load.sh load.sh~
+ test ../tut0/load.sh
+ echo 0
0

```

I was expecting output to also contain the line "in load.sh --------".  
Why is `test.sh` not calling `../tut0/load.sh` ?😕

Running load.sh directly, pwd prints the directory it was called from, rather than the file's directory:

```plaintext
$ bash -x ../tut0/load.sh
+ echo 'in load.sh --------'
in load.sh --------
+ pwd
/home/wolfv/Documents/developer/c++/demo/test_script/suite
+ ls
main main.cpp	main.cpp~ tests.sh tests.sh~
+ ls ../suite
main main.cpp	main.cpp~ tests.sh tests.sh~
+ ../suite/main
in main()-------
+ rc=1
+ echo rc:
rc:
+ echo 1
1
+ exit 1

```

---

<div class="post-metadata">

**Author:** ![RudiC](https://community.unix.com/letter_avatar/rudic/32/5_5575768a8748004e209b776fc1b2916d.png) [@RudiC](https://community.unix.com/u/RudiC)\
**Post date:** [January 20, 2017, 4:03pm UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/16 "2017-01-20T16:03:38Z")

</div>

Remove the `test` , let `if` interpret the exit code of `load` .sh immediately.

---

<div class="post-metadata">

**Author:** ![wolfv](https://community.unix.com/letter_avatar/wolfv/32/5_5575768a8748004e209b776fc1b2916d.png) [@wolfv](https://community.unix.com/u/wolfv)\
**Post date:** [January 20, 2017, 4:32pm UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/17 "2017-01-20T16:32:47Z")

</div>

> [@rudic](#):
>
> Remove the `test` , let `if` interpret the exit code of `load` .sh immediately.

That fixed it! :b:  
Thank you RudiC and everyone else that helped along the way.  
I could not have done it without you.

The following example works as intended.

$ cat tests.sh:

```plaintext
#!/bin/bash
echo "in tests.sh --------"
if ../tut0/load.sh
then
    echo "in tests.sh again --------"
    echo "0"
else
    echo "in tests.sh again --------"
    echo "1"
fi

```

$ cat ../tut0/load.sh:

```plaintext
#!/bin/bash
echo "in load.sh --------"
../suite/main
rc=$?
echo "rc:"
echo $rc
exit $rc

```

$ cat main.cpp:

```plaintext
#include <iostream>

int main()
{
    std::cout << "in main() -------\n";
    return 1; //EXIT_FAILURE
}

```

From the terminal:

```plaintext
$ ./tests.sh
in tests.sh --------
in load.sh --------
in main()-------
rc:
1
in tests.sh again --------
1

```

---

<div class="post-metadata">

**Author:** ![rovf](https://community.unix.com/letter_avatar/rovf/32/5_5575768a8748004e209b776fc1b2916d.png) [@rovf](https://community.unix.com/u/rovf)\
**Post date:** [January 23, 2017, 7:48am UTC](https://community.unix.com/t/returning-an-exit-code-from-a-bash-function/364621/18 "2017-01-23T07:48:40Z")

</div>

> [@wolfv](#):
>
> The following example is similar, but with load.sh script in a different directory.
> 
> ```plaintext
> #!/bin/bash
> if test ../tut0/load.sh
> then
> echo "0"
> else
> echo "1"
> fi
> 
> ```

You don't evaluate the exit code of load.sh. For example, if you would write

```plaintext
if test /usr/bin/false
then
  echo yes
fi

```

you would also get "yes" as answer.

You should write your code as

```plaintext
if ../tut0/load.sh
then
  echo 0
else
  echo 1
fi

```
