1. Overview
The return and exit commands are used for similar purposes. In general, the aim of return is to exit from a Bash function, while the objective of exit is to exit from a Bash script.
In this tutorial, we’ll discuss the differences between these two commands using several examples.
2. The return Command
return stops the execution of a Bash function.
If we supply an integer argument to return, it returns that argument to the function caller as the exit status. Otherwise, it returns the exit status of the last command executed before return to the function caller*.*
2.1. Using return to Exit From a Bash Function
Let’s examine the behavior of return with the following Bash script, examine_return.sh:
#!/bin/bash
foo()
{
if [ ! –z “$1” ]
then
return $1
fi
ls /non_existing_file >& /dev/null
return
}
foo 5
echo “The return value of \”foo 5\” : $?”
foo
echo “The return value of \”foo\” : $?”
The foo() function in this script checks whether we pass an argument to itself using the if [ ! –z “$1” ] statement. The conditional expression becomes true if we pass an argument to the foo() function. In this case, the function simply stops its execution and returns the value passed as an argument to the caller using the return $1 statement.
If we don’t pass an argument to the foo() function, then the conditional expression [ ! –z “$1” ] becomes false. In this case, the execution jumps to the ls /non_existing_file >& /dev/null statement. The ls command returns 2 if the file doesn’t exist. Then we exit from the foo() function calling return without any arguments. In fact, calling return explicitly is redundant since it’s the last command in the function.
Finally, we call the foo() function twice in the script. In the first call, we call it by passing the argument 5 to it. In the second call, we call it without passing any arguments. We print the exit status of the function using the echo command and $? in both cases.
Let’s run the script examine_return.sh and see the result:
$ examine_return.sh
The return value of ”foo 5” : 5
The return value of ”foo” : 2
As we see, the result is as expected. The exit status of the first function call is 5 since we pass 5 as the argument to the function. On the other hand, the exit status of the second function call is 2, as this is the exit status of the ls /non_existing_file >& /dev/null command, the last command executed before exiting from the function.
2.2. Using return to Exit From a Bash Script
What if we use return to exit from a script? Let’s try it by using examine_return_from_script.sh, a slightly modified version of the previous one we saw:
#!/bin/bash
foo()
{
if [ ! –z “$1” ]
then
return $1
fi
ls /non_existing_file >& /dev/null
return
}
foo 5
echo “The return value of \”foo 5\” : $?”
foo
echo “The return value of \”foo\” : $?”
return 0
This modified version of the script is the same as the previous one except for the one addition – the last return statement at the end of the script. Let’s run this script:
$ examine_return_from_script.sh
The return value of "foo 5" : 5
The return value of "foo" : 2
examine_return_from_script.sh: line 20: return: can only ‘return’ from a function or sourced script
We got an error, so we cannot use return to exit from a script.
However, as the output of the script suggests**, we can run the script using the source command:**
$ source examine_return_from_script.sh
The return value of ”foo 5” : 5
The return value of ”foo” : 2
$ echo $?
0
As is apparent from the output, the exit status of the script is 0, which is the result of return 0.
3. The exit Command
We use exit to exit from a Bash script. It doesn’t matter where we call it in the script. For example, we can call exit inside a Bash function or outside it.
Similar to return, it may take an integer argument. In that case, the script exits with the exit status set to the integer argument. If we don’t pass an argument to exit, it exits with the exit status set to the exit status of the last command executed before exit.
3.1. Using exit Inside a Bash Function
Let’s examine the behavior of exit in a Bash function with the following script, examine_exit.sh:
#!/bin/bash
foo()
{
if [ ! –z “$1” ]
then
exit $1
fi
ls /non_existing_file >& /dev/null
exit
}
if [ ! –z “$1” ]
then
foo $1
else
foo
fi
echo “This line will not be printed”
The foo() function in this script is very similar to the one in examine_return.sh. We just replaced the return commands with the exit commands. We also added an echo command to the end of the script to prove that the script exits immediately after exit.
Later, we call the foo() function in the script. If we run the script by passing an argument to it, we call the foo() function by passing the same argument to the function. If we run the script without any arguments, we call the foo() function without any arguments.
Now, let’s run the script:
$ examine_exit.sh 6
$ echo $?
6
$ examine_exit.sh
$ echo $?
2
In the first execution of the script, it exited with the exit status of 6. In the second execution, without any argument, the script exited with the exit status of 2, which is the exit status of the ls command before exit.
There was no output from the echo command in both the runs since we exited immediately from the script within the foo() function calls.
3.2. Using exit Outside a Bash Function
Let’s also show that we can use exit outside a Bash function to exit from the script. We have the following script, examine_exit_anywhere.sh:
#!/bin/bash
echo “This line will be printed”
exit 0
echo “But this line will not be printed”
foo()
{
if [ ! –z “$1” ]
then
exit $1
fi
ls /non_existing_file >& /dev/null
exit
}
if [ ! –z “$1” ]
then
foo $1
else
foo
fi
echo “This line will not be printed”
This script is very similar to the script examine_exit.sh we used earlier. We just added the two echo commands to the beginning of the script with the exit 0 command between them.
Let’s run the script:
$ examine_exit_anywhere.sh
This line will be printed
$ echo $?
0
As we see, the first echo was executed. The exit 0 after echo caused the script to exit with the exit status of 0. The commands in the rest of the script weren’t executed.
4. Using the trap Command With exit
Another difference between exit and return is related to the trap command. Normally, we use trap to process signals, but if we specify EXIT as the signal to trap, the action assigned to trap is executed when the script exits with exit.
Let’s clarify this with the following script, examine_trap.sh:
#!/bin/bash
trap “echo This line will be printed at exit” EXIT
foo()
{
echo “I am inside the foo function”
return 0
}
foo
echo “I am outside the foo function”
exit 0
trap at the beginning of the script just calls the echo command. The foo() function just prints a message and returns using return. Finally, after printing another message, we exit from the script with exit.
Let’s run the script:
$ examine_trap.sh
I am inside the foo function
I am outside the foo function
This line will be printed at exit
As we see, although we called return before exit, the message in trap was printed after exit. So, the shell executes a trap on EXIT for exit, but not for return.
5. Conclusion
In this article, we discussed the differences between the return and the exit commands.
We can call exit anywhere in the script, either inside a function or outside a function. This stops the execution of the script immediately.
We can call return in a function. This stops the execution of the function immediately. Using return for exiting from a script gives error. However, sourcing the script doesn’t give an error.
The shell executes the action in the trap command on EXIT for exit, but it doesn’t run it for return.