Implicit return in bash functions?
Clash Royale CLAN TAG#URR8PPP
up vote
3
down vote
favorite
Say I have a bash function like so:
gmx()
echo "foo";
will this function implicitly return the exit value of the echo
command, or is using return necessary?
gmx()
echo "foo";
return $?
I assume that the way bash works, the exit status of the final command of the bash function is the one that gets "returned", but not 100% certain.
bash shell-script bash-functions
add a comment |Â
up vote
3
down vote
favorite
Say I have a bash function like so:
gmx()
echo "foo";
will this function implicitly return the exit value of the echo
command, or is using return necessary?
gmx()
echo "foo";
return $?
I assume that the way bash works, the exit status of the final command of the bash function is the one that gets "returned", but not 100% certain.
bash shell-script bash-functions
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
Say I have a bash function like so:
gmx()
echo "foo";
will this function implicitly return the exit value of the echo
command, or is using return necessary?
gmx()
echo "foo";
return $?
I assume that the way bash works, the exit status of the final command of the bash function is the one that gets "returned", but not 100% certain.
bash shell-script bash-functions
Say I have a bash function like so:
gmx()
echo "foo";
will this function implicitly return the exit value of the echo
command, or is using return necessary?
gmx()
echo "foo";
return $?
I assume that the way bash works, the exit status of the final command of the bash function is the one that gets "returned", but not 100% certain.
bash shell-script bash-functions
asked May 28 at 7:14
Alexander Mills
1,878929
1,878929
add a comment |Â
add a comment |Â
4 Answers
4
active
oldest
votes
up vote
4
down vote
accepted
return
does an explicit return from a shell function or "dot script" (a sourced script). If return
is not executed, an implicit return is made at the end of the shell function or dot script.
If return
is executed without a parameter, it is equivalent of returning the exit status of the most recently executed command.
That is how return
works in all POSIX shells.
For example,
gmx ()
echo 'foo'
return "$?"
is therefore equivalent to
gmx ()
echo 'foo'
return
which is the same as
gmx ()
echo 'foo'
In general, it is very seldom that you need to use $?
at all. It is really only needed if you need to save it for future use, for example if you need to investigate its value multiple times (in which case you would assign its value to a variable and perform a series of tests on that variable).
2
One downside of usingreturn
is that for functions defined likef() (...; cmd; return)
, it prevents the optimisation that a few shells do of running thecmd
in the same process as the subshell. With many shells, that also means that the exit status of the function doesn't carry the information thatcmd
has been killed when it has (most shells can't retrieve that information anyway).
â Stéphane Chazelas
May 28 at 12:43
1
Note that with pdksh and some of its derivatives (like OpenBSDsh
orposh
), you'd needreturn -- "$?"
if there was a chance that the last command was a function that returned a negative number.mksh
(also based on pdksh) forbids functions from returning negative values.
â Stéphane Chazelas
May 28 at 16:55
thanks this helps, I guess I don't understand howreturn x
functions differently thanexit x
...the only thing I do know is thatreturn x
will not exit the current process.
â Alexander Mills
May 28 at 17:51
@AlexanderMills Well, it's what I said:return
is used to return from a function or a dot script.exit
does something completely different (terminates a process).
â Kusalananda
May 28 at 17:53
yeah that makes sense I think I am starting to get a better handle on this
â Alexander Mills
May 28 at 17:55
add a comment |Â
up vote
5
down vote
From the bash(1)
man page:
When executed, the exit status of a function is the exit status of the last command executed in the body.
right, and a corollary might be that the return statement is nothing more than the exit status?
â Alexander Mills
May 28 at 7:17
I guessreturn
is a builtin command - althoughreturn 1
is different thanexit 1
, etc so
â Alexander Mills
May 28 at 7:18
1
"return [n]: Causes a function to stop executing and return the value specified by n to its caller. If n is omitted, the return status is that of the last command executed in the function body." (ibid) So,return
forces the exit status of a function to a specific value if specified.
â Ignacio Vazquez-Abrams
May 28 at 7:21
1
@AlexandwrMills Yes,return
andexit
are both built-ins, exceptreturn
can only be used within function. You can't terminate a script withreturn
. Exit status is value that command returns.return
is command that returns that value. So "return statement is nothing more than the exit status" is just not quite accurate. One is a value, the other is command plus value.
â Sergiy Kolodyazhnyy
May 28 at 7:31
1
@AlexanderMills,return
returns from the function,exit
exits the whole shell. It's exactly the same as in, say C withreturn
vs.exit(n)
, orreturn
vs.sys.exit()
in Python.
â ilkkachu
May 28 at 7:56
 |Â
show 1 more comment
up vote
2
down vote
I'll just add a few notes of caution to the answers already provided:
Even though
return
has a very special meaning to the shell, from a syntax point of view, it is a shell builtin command and a return statement is parsed like any other simple command. So, that means that like in the argument of any other command,$?
when unquoted, would be subject to split+globSo you need to quote that
$?
to avoid it:return "$?"
return
usually doesn't accept any option (ksh93
's accepts the usual--help
,--man
,--author
... though). The only argument it expects (optional) is the return code. The range of accepted return codes varies from shell to shell, and whether any value outside 0..255 is properly reflected in$?
also varies from shell to shell. See Default exit code when process is terminated? for details on that.Most shells accept negative numbers (after all, the argument passed to the
_exit()
/exitgroup()
system call is anint
, so with values encompassing at least -231 to 231-1, so it only makes sense that shells accept the same range for its functions).Most shells use the
waitpid()
and co. API to retrieve that exit status however in which case, it's truncated to a number between 0 and 255 when stored in$?
. Even though invoking a function does not involve spawning a process and usedwaitpid()
to retrieve its exit status as all is done in the same process, many shells also mimic thatwaitpid()
behaviour when invoking functions. Which means that even if you callreturn
with a negative value,$?
will contain a positive number.Now, among those shells whose
return
accepts negative numbers (ksh88, ksh93, bash, zsh, pdksh and derivatives other than mksh, yash), there are a few (pdksh and yash) which need it written asreturn -- -123
as otherwise that-123
is taken as three-1
,-2
,-3
invalid options.As pdksh and its derivatives (like OpenBSD
sh
orposh
) preserve the negative number in$?
, that means that doingreturn "$?"
would fail when$?
contains a negative number (which would happen when the last run command was a function that returned a negative number).So
return -- "$?"
would be better in those shells. However note that while supported by most shells, that syntax is not POSIX and in practice not supported bymksh
and ash derivatives.So, to sum up, with pdksh-based shells, you may use negative numbers in arguments to functions, but if you do,
return "$@"
won't work. In other shells,return "$@"
will work and you should avoid using negative numbers (or numbers outside of 0..255) as arguments toreturn
.In all shells that I know, calling
return
from inside a subshell running inside a function will cause the subshell to exit (with the provided exit status if any or that of the last command run), but will not otherwise cause a return from the function (to me, it's unclear whether POSIX gives you that warranty, some argue thatexit
should be used instead of exit subshells inside functions). For instancef()
(return 3)
echo "still inside f. Exit status: $?"
f
echo "f exit status: $?"will output:
still inside f. Exit status: 3
f exit status: 0
Note that$(return 22)
fails with any version of bash.
â Isaac
May 29 at 5:12
add a comment |Â
up vote
0
down vote
Yes, the implicit return value of a function is the exit status of the last executed command. That is also true at any point of any shell script. At any point in the script execution sequence, the present exit status is the exit status of the last command executed. Even command executed as part of a variable assignment: var=$(exit 34)
. The difference with functions is that a function could change the exit status at the end of execution of the function.
The alternative way to change the "present exit status" is to start a sub shell and exit it with any needed exit status:
$ $(exit 34)
$ echo "$?"
34
And yes, the exit status expansion do need to be quoted:
$ IFS='123'
$ $(exit 34)
$ echo $?
4
A (exit 34)
also work.
Some may argue that a more robust construct should be $(return 34)
, and that an exit should "exit" the script being executed. But $(return 34)
does not work with any version of bash. So, it is not portable.
The safest way to set an exit status is to use it as it was designed to work, define and return
from a function:
exitstatus() return "$1:-"$?"";
So, in the end of a function. it is exactly equivalent to have either nothing or return
or return "$?"
. The end of a function does not need to mean the "last code line of a function".
#!/bin/sh
exitstatus() a="$1:-"$?""; return "$a";
gmx()
if [ "$1" = "one" ]; then
printf 'foo ';
exitstatus 78
return "$?"
elif [ "$1" = "two" ]; then
printf 'baz ';
exitstatus 89
return
else
printf 'baz ';
exitstatus 90
fi
Will print:
$ ./script
foo 78
baz 89
baz 90
The only practical use for "$?"
is to either print its value: echo "$?"
or to store it in a variable (as it is an ephemeral value and change with every command executed): exitstatus=$?
(remember to quote the variable in commands like export EXITSTATUS="$?"
.
In the return
command, the valid range of values is generally 0 to 255, but understand that values of 126 + n
are used by some shells to signal special exit status, so, the general recommendation is to use 0-125.
add a comment |Â
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
accepted
return
does an explicit return from a shell function or "dot script" (a sourced script). If return
is not executed, an implicit return is made at the end of the shell function or dot script.
If return
is executed without a parameter, it is equivalent of returning the exit status of the most recently executed command.
That is how return
works in all POSIX shells.
For example,
gmx ()
echo 'foo'
return "$?"
is therefore equivalent to
gmx ()
echo 'foo'
return
which is the same as
gmx ()
echo 'foo'
In general, it is very seldom that you need to use $?
at all. It is really only needed if you need to save it for future use, for example if you need to investigate its value multiple times (in which case you would assign its value to a variable and perform a series of tests on that variable).
2
One downside of usingreturn
is that for functions defined likef() (...; cmd; return)
, it prevents the optimisation that a few shells do of running thecmd
in the same process as the subshell. With many shells, that also means that the exit status of the function doesn't carry the information thatcmd
has been killed when it has (most shells can't retrieve that information anyway).
â Stéphane Chazelas
May 28 at 12:43
1
Note that with pdksh and some of its derivatives (like OpenBSDsh
orposh
), you'd needreturn -- "$?"
if there was a chance that the last command was a function that returned a negative number.mksh
(also based on pdksh) forbids functions from returning negative values.
â Stéphane Chazelas
May 28 at 16:55
thanks this helps, I guess I don't understand howreturn x
functions differently thanexit x
...the only thing I do know is thatreturn x
will not exit the current process.
â Alexander Mills
May 28 at 17:51
@AlexanderMills Well, it's what I said:return
is used to return from a function or a dot script.exit
does something completely different (terminates a process).
â Kusalananda
May 28 at 17:53
yeah that makes sense I think I am starting to get a better handle on this
â Alexander Mills
May 28 at 17:55
add a comment |Â
up vote
4
down vote
accepted
return
does an explicit return from a shell function or "dot script" (a sourced script). If return
is not executed, an implicit return is made at the end of the shell function or dot script.
If return
is executed without a parameter, it is equivalent of returning the exit status of the most recently executed command.
That is how return
works in all POSIX shells.
For example,
gmx ()
echo 'foo'
return "$?"
is therefore equivalent to
gmx ()
echo 'foo'
return
which is the same as
gmx ()
echo 'foo'
In general, it is very seldom that you need to use $?
at all. It is really only needed if you need to save it for future use, for example if you need to investigate its value multiple times (in which case you would assign its value to a variable and perform a series of tests on that variable).
2
One downside of usingreturn
is that for functions defined likef() (...; cmd; return)
, it prevents the optimisation that a few shells do of running thecmd
in the same process as the subshell. With many shells, that also means that the exit status of the function doesn't carry the information thatcmd
has been killed when it has (most shells can't retrieve that information anyway).
â Stéphane Chazelas
May 28 at 12:43
1
Note that with pdksh and some of its derivatives (like OpenBSDsh
orposh
), you'd needreturn -- "$?"
if there was a chance that the last command was a function that returned a negative number.mksh
(also based on pdksh) forbids functions from returning negative values.
â Stéphane Chazelas
May 28 at 16:55
thanks this helps, I guess I don't understand howreturn x
functions differently thanexit x
...the only thing I do know is thatreturn x
will not exit the current process.
â Alexander Mills
May 28 at 17:51
@AlexanderMills Well, it's what I said:return
is used to return from a function or a dot script.exit
does something completely different (terminates a process).
â Kusalananda
May 28 at 17:53
yeah that makes sense I think I am starting to get a better handle on this
â Alexander Mills
May 28 at 17:55
add a comment |Â
up vote
4
down vote
accepted
up vote
4
down vote
accepted
return
does an explicit return from a shell function or "dot script" (a sourced script). If return
is not executed, an implicit return is made at the end of the shell function or dot script.
If return
is executed without a parameter, it is equivalent of returning the exit status of the most recently executed command.
That is how return
works in all POSIX shells.
For example,
gmx ()
echo 'foo'
return "$?"
is therefore equivalent to
gmx ()
echo 'foo'
return
which is the same as
gmx ()
echo 'foo'
In general, it is very seldom that you need to use $?
at all. It is really only needed if you need to save it for future use, for example if you need to investigate its value multiple times (in which case you would assign its value to a variable and perform a series of tests on that variable).
return
does an explicit return from a shell function or "dot script" (a sourced script). If return
is not executed, an implicit return is made at the end of the shell function or dot script.
If return
is executed without a parameter, it is equivalent of returning the exit status of the most recently executed command.
That is how return
works in all POSIX shells.
For example,
gmx ()
echo 'foo'
return "$?"
is therefore equivalent to
gmx ()
echo 'foo'
return
which is the same as
gmx ()
echo 'foo'
In general, it is very seldom that you need to use $?
at all. It is really only needed if you need to save it for future use, for example if you need to investigate its value multiple times (in which case you would assign its value to a variable and perform a series of tests on that variable).
edited May 28 at 12:41
Stéphane Chazelas
279k53513844
279k53513844
answered May 28 at 8:37
Kusalananda
102k13199314
102k13199314
2
One downside of usingreturn
is that for functions defined likef() (...; cmd; return)
, it prevents the optimisation that a few shells do of running thecmd
in the same process as the subshell. With many shells, that also means that the exit status of the function doesn't carry the information thatcmd
has been killed when it has (most shells can't retrieve that information anyway).
â Stéphane Chazelas
May 28 at 12:43
1
Note that with pdksh and some of its derivatives (like OpenBSDsh
orposh
), you'd needreturn -- "$?"
if there was a chance that the last command was a function that returned a negative number.mksh
(also based on pdksh) forbids functions from returning negative values.
â Stéphane Chazelas
May 28 at 16:55
thanks this helps, I guess I don't understand howreturn x
functions differently thanexit x
...the only thing I do know is thatreturn x
will not exit the current process.
â Alexander Mills
May 28 at 17:51
@AlexanderMills Well, it's what I said:return
is used to return from a function or a dot script.exit
does something completely different (terminates a process).
â Kusalananda
May 28 at 17:53
yeah that makes sense I think I am starting to get a better handle on this
â Alexander Mills
May 28 at 17:55
add a comment |Â
2
One downside of usingreturn
is that for functions defined likef() (...; cmd; return)
, it prevents the optimisation that a few shells do of running thecmd
in the same process as the subshell. With many shells, that also means that the exit status of the function doesn't carry the information thatcmd
has been killed when it has (most shells can't retrieve that information anyway).
â Stéphane Chazelas
May 28 at 12:43
1
Note that with pdksh and some of its derivatives (like OpenBSDsh
orposh
), you'd needreturn -- "$?"
if there was a chance that the last command was a function that returned a negative number.mksh
(also based on pdksh) forbids functions from returning negative values.
â Stéphane Chazelas
May 28 at 16:55
thanks this helps, I guess I don't understand howreturn x
functions differently thanexit x
...the only thing I do know is thatreturn x
will not exit the current process.
â Alexander Mills
May 28 at 17:51
@AlexanderMills Well, it's what I said:return
is used to return from a function or a dot script.exit
does something completely different (terminates a process).
â Kusalananda
May 28 at 17:53
yeah that makes sense I think I am starting to get a better handle on this
â Alexander Mills
May 28 at 17:55
2
2
One downside of using
return
is that for functions defined like f() (...; cmd; return)
, it prevents the optimisation that a few shells do of running the cmd
in the same process as the subshell. With many shells, that also means that the exit status of the function doesn't carry the information that cmd
has been killed when it has (most shells can't retrieve that information anyway).â Stéphane Chazelas
May 28 at 12:43
One downside of using
return
is that for functions defined like f() (...; cmd; return)
, it prevents the optimisation that a few shells do of running the cmd
in the same process as the subshell. With many shells, that also means that the exit status of the function doesn't carry the information that cmd
has been killed when it has (most shells can't retrieve that information anyway).â Stéphane Chazelas
May 28 at 12:43
1
1
Note that with pdksh and some of its derivatives (like OpenBSD
sh
or posh
), you'd need return -- "$?"
if there was a chance that the last command was a function that returned a negative number. mksh
(also based on pdksh) forbids functions from returning negative values.â Stéphane Chazelas
May 28 at 16:55
Note that with pdksh and some of its derivatives (like OpenBSD
sh
or posh
), you'd need return -- "$?"
if there was a chance that the last command was a function that returned a negative number. mksh
(also based on pdksh) forbids functions from returning negative values.â Stéphane Chazelas
May 28 at 16:55
thanks this helps, I guess I don't understand how
return x
functions differently than exit x
...the only thing I do know is that return x
will not exit the current process.â Alexander Mills
May 28 at 17:51
thanks this helps, I guess I don't understand how
return x
functions differently than exit x
...the only thing I do know is that return x
will not exit the current process.â Alexander Mills
May 28 at 17:51
@AlexanderMills Well, it's what I said:
return
is used to return from a function or a dot script. exit
does something completely different (terminates a process).â Kusalananda
May 28 at 17:53
@AlexanderMills Well, it's what I said:
return
is used to return from a function or a dot script. exit
does something completely different (terminates a process).â Kusalananda
May 28 at 17:53
yeah that makes sense I think I am starting to get a better handle on this
â Alexander Mills
May 28 at 17:55
yeah that makes sense I think I am starting to get a better handle on this
â Alexander Mills
May 28 at 17:55
add a comment |Â
up vote
5
down vote
From the bash(1)
man page:
When executed, the exit status of a function is the exit status of the last command executed in the body.
right, and a corollary might be that the return statement is nothing more than the exit status?
â Alexander Mills
May 28 at 7:17
I guessreturn
is a builtin command - althoughreturn 1
is different thanexit 1
, etc so
â Alexander Mills
May 28 at 7:18
1
"return [n]: Causes a function to stop executing and return the value specified by n to its caller. If n is omitted, the return status is that of the last command executed in the function body." (ibid) So,return
forces the exit status of a function to a specific value if specified.
â Ignacio Vazquez-Abrams
May 28 at 7:21
1
@AlexandwrMills Yes,return
andexit
are both built-ins, exceptreturn
can only be used within function. You can't terminate a script withreturn
. Exit status is value that command returns.return
is command that returns that value. So "return statement is nothing more than the exit status" is just not quite accurate. One is a value, the other is command plus value.
â Sergiy Kolodyazhnyy
May 28 at 7:31
1
@AlexanderMills,return
returns from the function,exit
exits the whole shell. It's exactly the same as in, say C withreturn
vs.exit(n)
, orreturn
vs.sys.exit()
in Python.
â ilkkachu
May 28 at 7:56
 |Â
show 1 more comment
up vote
5
down vote
From the bash(1)
man page:
When executed, the exit status of a function is the exit status of the last command executed in the body.
right, and a corollary might be that the return statement is nothing more than the exit status?
â Alexander Mills
May 28 at 7:17
I guessreturn
is a builtin command - althoughreturn 1
is different thanexit 1
, etc so
â Alexander Mills
May 28 at 7:18
1
"return [n]: Causes a function to stop executing and return the value specified by n to its caller. If n is omitted, the return status is that of the last command executed in the function body." (ibid) So,return
forces the exit status of a function to a specific value if specified.
â Ignacio Vazquez-Abrams
May 28 at 7:21
1
@AlexandwrMills Yes,return
andexit
are both built-ins, exceptreturn
can only be used within function. You can't terminate a script withreturn
. Exit status is value that command returns.return
is command that returns that value. So "return statement is nothing more than the exit status" is just not quite accurate. One is a value, the other is command plus value.
â Sergiy Kolodyazhnyy
May 28 at 7:31
1
@AlexanderMills,return
returns from the function,exit
exits the whole shell. It's exactly the same as in, say C withreturn
vs.exit(n)
, orreturn
vs.sys.exit()
in Python.
â ilkkachu
May 28 at 7:56
 |Â
show 1 more comment
up vote
5
down vote
up vote
5
down vote
From the bash(1)
man page:
When executed, the exit status of a function is the exit status of the last command executed in the body.
From the bash(1)
man page:
When executed, the exit status of a function is the exit status of the last command executed in the body.
answered May 28 at 7:16
Ignacio Vazquez-Abrams
32k66780
32k66780
right, and a corollary might be that the return statement is nothing more than the exit status?
â Alexander Mills
May 28 at 7:17
I guessreturn
is a builtin command - althoughreturn 1
is different thanexit 1
, etc so
â Alexander Mills
May 28 at 7:18
1
"return [n]: Causes a function to stop executing and return the value specified by n to its caller. If n is omitted, the return status is that of the last command executed in the function body." (ibid) So,return
forces the exit status of a function to a specific value if specified.
â Ignacio Vazquez-Abrams
May 28 at 7:21
1
@AlexandwrMills Yes,return
andexit
are both built-ins, exceptreturn
can only be used within function. You can't terminate a script withreturn
. Exit status is value that command returns.return
is command that returns that value. So "return statement is nothing more than the exit status" is just not quite accurate. One is a value, the other is command plus value.
â Sergiy Kolodyazhnyy
May 28 at 7:31
1
@AlexanderMills,return
returns from the function,exit
exits the whole shell. It's exactly the same as in, say C withreturn
vs.exit(n)
, orreturn
vs.sys.exit()
in Python.
â ilkkachu
May 28 at 7:56
 |Â
show 1 more comment
right, and a corollary might be that the return statement is nothing more than the exit status?
â Alexander Mills
May 28 at 7:17
I guessreturn
is a builtin command - althoughreturn 1
is different thanexit 1
, etc so
â Alexander Mills
May 28 at 7:18
1
"return [n]: Causes a function to stop executing and return the value specified by n to its caller. If n is omitted, the return status is that of the last command executed in the function body." (ibid) So,return
forces the exit status of a function to a specific value if specified.
â Ignacio Vazquez-Abrams
May 28 at 7:21
1
@AlexandwrMills Yes,return
andexit
are both built-ins, exceptreturn
can only be used within function. You can't terminate a script withreturn
. Exit status is value that command returns.return
is command that returns that value. So "return statement is nothing more than the exit status" is just not quite accurate. One is a value, the other is command plus value.
â Sergiy Kolodyazhnyy
May 28 at 7:31
1
@AlexanderMills,return
returns from the function,exit
exits the whole shell. It's exactly the same as in, say C withreturn
vs.exit(n)
, orreturn
vs.sys.exit()
in Python.
â ilkkachu
May 28 at 7:56
right, and a corollary might be that the return statement is nothing more than the exit status?
â Alexander Mills
May 28 at 7:17
right, and a corollary might be that the return statement is nothing more than the exit status?
â Alexander Mills
May 28 at 7:17
I guess
return
is a builtin command - although return 1
is different than exit 1
, etc soâ Alexander Mills
May 28 at 7:18
I guess
return
is a builtin command - although return 1
is different than exit 1
, etc soâ Alexander Mills
May 28 at 7:18
1
1
"return [n]: Causes a function to stop executing and return the value specified by n to its caller. If n is omitted, the return status is that of the last command executed in the function body." (ibid) So,
return
forces the exit status of a function to a specific value if specified.â Ignacio Vazquez-Abrams
May 28 at 7:21
"return [n]: Causes a function to stop executing and return the value specified by n to its caller. If n is omitted, the return status is that of the last command executed in the function body." (ibid) So,
return
forces the exit status of a function to a specific value if specified.â Ignacio Vazquez-Abrams
May 28 at 7:21
1
1
@AlexandwrMills Yes,
return
and exit
are both built-ins, except return
can only be used within function. You can't terminate a script with return
. Exit status is value that command returns. return
is command that returns that value. So "return statement is nothing more than the exit status" is just not quite accurate. One is a value, the other is command plus value.â Sergiy Kolodyazhnyy
May 28 at 7:31
@AlexandwrMills Yes,
return
and exit
are both built-ins, except return
can only be used within function. You can't terminate a script with return
. Exit status is value that command returns. return
is command that returns that value. So "return statement is nothing more than the exit status" is just not quite accurate. One is a value, the other is command plus value.â Sergiy Kolodyazhnyy
May 28 at 7:31
1
1
@AlexanderMills,
return
returns from the function, exit
exits the whole shell. It's exactly the same as in, say C with return
vs. exit(n)
, or return
vs. sys.exit()
in Python.â ilkkachu
May 28 at 7:56
@AlexanderMills,
return
returns from the function, exit
exits the whole shell. It's exactly the same as in, say C with return
vs. exit(n)
, or return
vs. sys.exit()
in Python.â ilkkachu
May 28 at 7:56
 |Â
show 1 more comment
up vote
2
down vote
I'll just add a few notes of caution to the answers already provided:
Even though
return
has a very special meaning to the shell, from a syntax point of view, it is a shell builtin command and a return statement is parsed like any other simple command. So, that means that like in the argument of any other command,$?
when unquoted, would be subject to split+globSo you need to quote that
$?
to avoid it:return "$?"
return
usually doesn't accept any option (ksh93
's accepts the usual--help
,--man
,--author
... though). The only argument it expects (optional) is the return code. The range of accepted return codes varies from shell to shell, and whether any value outside 0..255 is properly reflected in$?
also varies from shell to shell. See Default exit code when process is terminated? for details on that.Most shells accept negative numbers (after all, the argument passed to the
_exit()
/exitgroup()
system call is anint
, so with values encompassing at least -231 to 231-1, so it only makes sense that shells accept the same range for its functions).Most shells use the
waitpid()
and co. API to retrieve that exit status however in which case, it's truncated to a number between 0 and 255 when stored in$?
. Even though invoking a function does not involve spawning a process and usedwaitpid()
to retrieve its exit status as all is done in the same process, many shells also mimic thatwaitpid()
behaviour when invoking functions. Which means that even if you callreturn
with a negative value,$?
will contain a positive number.Now, among those shells whose
return
accepts negative numbers (ksh88, ksh93, bash, zsh, pdksh and derivatives other than mksh, yash), there are a few (pdksh and yash) which need it written asreturn -- -123
as otherwise that-123
is taken as three-1
,-2
,-3
invalid options.As pdksh and its derivatives (like OpenBSD
sh
orposh
) preserve the negative number in$?
, that means that doingreturn "$?"
would fail when$?
contains a negative number (which would happen when the last run command was a function that returned a negative number).So
return -- "$?"
would be better in those shells. However note that while supported by most shells, that syntax is not POSIX and in practice not supported bymksh
and ash derivatives.So, to sum up, with pdksh-based shells, you may use negative numbers in arguments to functions, but if you do,
return "$@"
won't work. In other shells,return "$@"
will work and you should avoid using negative numbers (or numbers outside of 0..255) as arguments toreturn
.In all shells that I know, calling
return
from inside a subshell running inside a function will cause the subshell to exit (with the provided exit status if any or that of the last command run), but will not otherwise cause a return from the function (to me, it's unclear whether POSIX gives you that warranty, some argue thatexit
should be used instead of exit subshells inside functions). For instancef()
(return 3)
echo "still inside f. Exit status: $?"
f
echo "f exit status: $?"will output:
still inside f. Exit status: 3
f exit status: 0
Note that$(return 22)
fails with any version of bash.
â Isaac
May 29 at 5:12
add a comment |Â
up vote
2
down vote
I'll just add a few notes of caution to the answers already provided:
Even though
return
has a very special meaning to the shell, from a syntax point of view, it is a shell builtin command and a return statement is parsed like any other simple command. So, that means that like in the argument of any other command,$?
when unquoted, would be subject to split+globSo you need to quote that
$?
to avoid it:return "$?"
return
usually doesn't accept any option (ksh93
's accepts the usual--help
,--man
,--author
... though). The only argument it expects (optional) is the return code. The range of accepted return codes varies from shell to shell, and whether any value outside 0..255 is properly reflected in$?
also varies from shell to shell. See Default exit code when process is terminated? for details on that.Most shells accept negative numbers (after all, the argument passed to the
_exit()
/exitgroup()
system call is anint
, so with values encompassing at least -231 to 231-1, so it only makes sense that shells accept the same range for its functions).Most shells use the
waitpid()
and co. API to retrieve that exit status however in which case, it's truncated to a number between 0 and 255 when stored in$?
. Even though invoking a function does not involve spawning a process and usedwaitpid()
to retrieve its exit status as all is done in the same process, many shells also mimic thatwaitpid()
behaviour when invoking functions. Which means that even if you callreturn
with a negative value,$?
will contain a positive number.Now, among those shells whose
return
accepts negative numbers (ksh88, ksh93, bash, zsh, pdksh and derivatives other than mksh, yash), there are a few (pdksh and yash) which need it written asreturn -- -123
as otherwise that-123
is taken as three-1
,-2
,-3
invalid options.As pdksh and its derivatives (like OpenBSD
sh
orposh
) preserve the negative number in$?
, that means that doingreturn "$?"
would fail when$?
contains a negative number (which would happen when the last run command was a function that returned a negative number).So
return -- "$?"
would be better in those shells. However note that while supported by most shells, that syntax is not POSIX and in practice not supported bymksh
and ash derivatives.So, to sum up, with pdksh-based shells, you may use negative numbers in arguments to functions, but if you do,
return "$@"
won't work. In other shells,return "$@"
will work and you should avoid using negative numbers (or numbers outside of 0..255) as arguments toreturn
.In all shells that I know, calling
return
from inside a subshell running inside a function will cause the subshell to exit (with the provided exit status if any or that of the last command run), but will not otherwise cause a return from the function (to me, it's unclear whether POSIX gives you that warranty, some argue thatexit
should be used instead of exit subshells inside functions). For instancef()
(return 3)
echo "still inside f. Exit status: $?"
f
echo "f exit status: $?"will output:
still inside f. Exit status: 3
f exit status: 0
Note that$(return 22)
fails with any version of bash.
â Isaac
May 29 at 5:12
add a comment |Â
up vote
2
down vote
up vote
2
down vote
I'll just add a few notes of caution to the answers already provided:
Even though
return
has a very special meaning to the shell, from a syntax point of view, it is a shell builtin command and a return statement is parsed like any other simple command. So, that means that like in the argument of any other command,$?
when unquoted, would be subject to split+globSo you need to quote that
$?
to avoid it:return "$?"
return
usually doesn't accept any option (ksh93
's accepts the usual--help
,--man
,--author
... though). The only argument it expects (optional) is the return code. The range of accepted return codes varies from shell to shell, and whether any value outside 0..255 is properly reflected in$?
also varies from shell to shell. See Default exit code when process is terminated? for details on that.Most shells accept negative numbers (after all, the argument passed to the
_exit()
/exitgroup()
system call is anint
, so with values encompassing at least -231 to 231-1, so it only makes sense that shells accept the same range for its functions).Most shells use the
waitpid()
and co. API to retrieve that exit status however in which case, it's truncated to a number between 0 and 255 when stored in$?
. Even though invoking a function does not involve spawning a process and usedwaitpid()
to retrieve its exit status as all is done in the same process, many shells also mimic thatwaitpid()
behaviour when invoking functions. Which means that even if you callreturn
with a negative value,$?
will contain a positive number.Now, among those shells whose
return
accepts negative numbers (ksh88, ksh93, bash, zsh, pdksh and derivatives other than mksh, yash), there are a few (pdksh and yash) which need it written asreturn -- -123
as otherwise that-123
is taken as three-1
,-2
,-3
invalid options.As pdksh and its derivatives (like OpenBSD
sh
orposh
) preserve the negative number in$?
, that means that doingreturn "$?"
would fail when$?
contains a negative number (which would happen when the last run command was a function that returned a negative number).So
return -- "$?"
would be better in those shells. However note that while supported by most shells, that syntax is not POSIX and in practice not supported bymksh
and ash derivatives.So, to sum up, with pdksh-based shells, you may use negative numbers in arguments to functions, but if you do,
return "$@"
won't work. In other shells,return "$@"
will work and you should avoid using negative numbers (or numbers outside of 0..255) as arguments toreturn
.In all shells that I know, calling
return
from inside a subshell running inside a function will cause the subshell to exit (with the provided exit status if any or that of the last command run), but will not otherwise cause a return from the function (to me, it's unclear whether POSIX gives you that warranty, some argue thatexit
should be used instead of exit subshells inside functions). For instancef()
(return 3)
echo "still inside f. Exit status: $?"
f
echo "f exit status: $?"will output:
still inside f. Exit status: 3
f exit status: 0
I'll just add a few notes of caution to the answers already provided:
Even though
return
has a very special meaning to the shell, from a syntax point of view, it is a shell builtin command and a return statement is parsed like any other simple command. So, that means that like in the argument of any other command,$?
when unquoted, would be subject to split+globSo you need to quote that
$?
to avoid it:return "$?"
return
usually doesn't accept any option (ksh93
's accepts the usual--help
,--man
,--author
... though). The only argument it expects (optional) is the return code. The range of accepted return codes varies from shell to shell, and whether any value outside 0..255 is properly reflected in$?
also varies from shell to shell. See Default exit code when process is terminated? for details on that.Most shells accept negative numbers (after all, the argument passed to the
_exit()
/exitgroup()
system call is anint
, so with values encompassing at least -231 to 231-1, so it only makes sense that shells accept the same range for its functions).Most shells use the
waitpid()
and co. API to retrieve that exit status however in which case, it's truncated to a number between 0 and 255 when stored in$?
. Even though invoking a function does not involve spawning a process and usedwaitpid()
to retrieve its exit status as all is done in the same process, many shells also mimic thatwaitpid()
behaviour when invoking functions. Which means that even if you callreturn
with a negative value,$?
will contain a positive number.Now, among those shells whose
return
accepts negative numbers (ksh88, ksh93, bash, zsh, pdksh and derivatives other than mksh, yash), there are a few (pdksh and yash) which need it written asreturn -- -123
as otherwise that-123
is taken as three-1
,-2
,-3
invalid options.As pdksh and its derivatives (like OpenBSD
sh
orposh
) preserve the negative number in$?
, that means that doingreturn "$?"
would fail when$?
contains a negative number (which would happen when the last run command was a function that returned a negative number).So
return -- "$?"
would be better in those shells. However note that while supported by most shells, that syntax is not POSIX and in practice not supported bymksh
and ash derivatives.So, to sum up, with pdksh-based shells, you may use negative numbers in arguments to functions, but if you do,
return "$@"
won't work. In other shells,return "$@"
will work and you should avoid using negative numbers (or numbers outside of 0..255) as arguments toreturn
.In all shells that I know, calling
return
from inside a subshell running inside a function will cause the subshell to exit (with the provided exit status if any or that of the last command run), but will not otherwise cause a return from the function (to me, it's unclear whether POSIX gives you that warranty, some argue thatexit
should be used instead of exit subshells inside functions). For instancef()
(return 3)
echo "still inside f. Exit status: $?"
f
echo "f exit status: $?"will output:
still inside f. Exit status: 3
f exit status: 0
edited May 28 at 18:05
answered May 28 at 18:00
Stéphane Chazelas
279k53513844
279k53513844
Note that$(return 22)
fails with any version of bash.
â Isaac
May 29 at 5:12
add a comment |Â
Note that$(return 22)
fails with any version of bash.
â Isaac
May 29 at 5:12
Note that
$(return 22)
fails with any version of bash.â Isaac
May 29 at 5:12
Note that
$(return 22)
fails with any version of bash.â Isaac
May 29 at 5:12
add a comment |Â
up vote
0
down vote
Yes, the implicit return value of a function is the exit status of the last executed command. That is also true at any point of any shell script. At any point in the script execution sequence, the present exit status is the exit status of the last command executed. Even command executed as part of a variable assignment: var=$(exit 34)
. The difference with functions is that a function could change the exit status at the end of execution of the function.
The alternative way to change the "present exit status" is to start a sub shell and exit it with any needed exit status:
$ $(exit 34)
$ echo "$?"
34
And yes, the exit status expansion do need to be quoted:
$ IFS='123'
$ $(exit 34)
$ echo $?
4
A (exit 34)
also work.
Some may argue that a more robust construct should be $(return 34)
, and that an exit should "exit" the script being executed. But $(return 34)
does not work with any version of bash. So, it is not portable.
The safest way to set an exit status is to use it as it was designed to work, define and return
from a function:
exitstatus() return "$1:-"$?"";
So, in the end of a function. it is exactly equivalent to have either nothing or return
or return "$?"
. The end of a function does not need to mean the "last code line of a function".
#!/bin/sh
exitstatus() a="$1:-"$?""; return "$a";
gmx()
if [ "$1" = "one" ]; then
printf 'foo ';
exitstatus 78
return "$?"
elif [ "$1" = "two" ]; then
printf 'baz ';
exitstatus 89
return
else
printf 'baz ';
exitstatus 90
fi
Will print:
$ ./script
foo 78
baz 89
baz 90
The only practical use for "$?"
is to either print its value: echo "$?"
or to store it in a variable (as it is an ephemeral value and change with every command executed): exitstatus=$?
(remember to quote the variable in commands like export EXITSTATUS="$?"
.
In the return
command, the valid range of values is generally 0 to 255, but understand that values of 126 + n
are used by some shells to signal special exit status, so, the general recommendation is to use 0-125.
add a comment |Â
up vote
0
down vote
Yes, the implicit return value of a function is the exit status of the last executed command. That is also true at any point of any shell script. At any point in the script execution sequence, the present exit status is the exit status of the last command executed. Even command executed as part of a variable assignment: var=$(exit 34)
. The difference with functions is that a function could change the exit status at the end of execution of the function.
The alternative way to change the "present exit status" is to start a sub shell and exit it with any needed exit status:
$ $(exit 34)
$ echo "$?"
34
And yes, the exit status expansion do need to be quoted:
$ IFS='123'
$ $(exit 34)
$ echo $?
4
A (exit 34)
also work.
Some may argue that a more robust construct should be $(return 34)
, and that an exit should "exit" the script being executed. But $(return 34)
does not work with any version of bash. So, it is not portable.
The safest way to set an exit status is to use it as it was designed to work, define and return
from a function:
exitstatus() return "$1:-"$?"";
So, in the end of a function. it is exactly equivalent to have either nothing or return
or return "$?"
. The end of a function does not need to mean the "last code line of a function".
#!/bin/sh
exitstatus() a="$1:-"$?""; return "$a";
gmx()
if [ "$1" = "one" ]; then
printf 'foo ';
exitstatus 78
return "$?"
elif [ "$1" = "two" ]; then
printf 'baz ';
exitstatus 89
return
else
printf 'baz ';
exitstatus 90
fi
Will print:
$ ./script
foo 78
baz 89
baz 90
The only practical use for "$?"
is to either print its value: echo "$?"
or to store it in a variable (as it is an ephemeral value and change with every command executed): exitstatus=$?
(remember to quote the variable in commands like export EXITSTATUS="$?"
.
In the return
command, the valid range of values is generally 0 to 255, but understand that values of 126 + n
are used by some shells to signal special exit status, so, the general recommendation is to use 0-125.
add a comment |Â
up vote
0
down vote
up vote
0
down vote
Yes, the implicit return value of a function is the exit status of the last executed command. That is also true at any point of any shell script. At any point in the script execution sequence, the present exit status is the exit status of the last command executed. Even command executed as part of a variable assignment: var=$(exit 34)
. The difference with functions is that a function could change the exit status at the end of execution of the function.
The alternative way to change the "present exit status" is to start a sub shell and exit it with any needed exit status:
$ $(exit 34)
$ echo "$?"
34
And yes, the exit status expansion do need to be quoted:
$ IFS='123'
$ $(exit 34)
$ echo $?
4
A (exit 34)
also work.
Some may argue that a more robust construct should be $(return 34)
, and that an exit should "exit" the script being executed. But $(return 34)
does not work with any version of bash. So, it is not portable.
The safest way to set an exit status is to use it as it was designed to work, define and return
from a function:
exitstatus() return "$1:-"$?"";
So, in the end of a function. it is exactly equivalent to have either nothing or return
or return "$?"
. The end of a function does not need to mean the "last code line of a function".
#!/bin/sh
exitstatus() a="$1:-"$?""; return "$a";
gmx()
if [ "$1" = "one" ]; then
printf 'foo ';
exitstatus 78
return "$?"
elif [ "$1" = "two" ]; then
printf 'baz ';
exitstatus 89
return
else
printf 'baz ';
exitstatus 90
fi
Will print:
$ ./script
foo 78
baz 89
baz 90
The only practical use for "$?"
is to either print its value: echo "$?"
or to store it in a variable (as it is an ephemeral value and change with every command executed): exitstatus=$?
(remember to quote the variable in commands like export EXITSTATUS="$?"
.
In the return
command, the valid range of values is generally 0 to 255, but understand that values of 126 + n
are used by some shells to signal special exit status, so, the general recommendation is to use 0-125.
Yes, the implicit return value of a function is the exit status of the last executed command. That is also true at any point of any shell script. At any point in the script execution sequence, the present exit status is the exit status of the last command executed. Even command executed as part of a variable assignment: var=$(exit 34)
. The difference with functions is that a function could change the exit status at the end of execution of the function.
The alternative way to change the "present exit status" is to start a sub shell and exit it with any needed exit status:
$ $(exit 34)
$ echo "$?"
34
And yes, the exit status expansion do need to be quoted:
$ IFS='123'
$ $(exit 34)
$ echo $?
4
A (exit 34)
also work.
Some may argue that a more robust construct should be $(return 34)
, and that an exit should "exit" the script being executed. But $(return 34)
does not work with any version of bash. So, it is not portable.
The safest way to set an exit status is to use it as it was designed to work, define and return
from a function:
exitstatus() return "$1:-"$?"";
So, in the end of a function. it is exactly equivalent to have either nothing or return
or return "$?"
. The end of a function does not need to mean the "last code line of a function".
#!/bin/sh
exitstatus() a="$1:-"$?""; return "$a";
gmx()
if [ "$1" = "one" ]; then
printf 'foo ';
exitstatus 78
return "$?"
elif [ "$1" = "two" ]; then
printf 'baz ';
exitstatus 89
return
else
printf 'baz ';
exitstatus 90
fi
Will print:
$ ./script
foo 78
baz 89
baz 90
The only practical use for "$?"
is to either print its value: echo "$?"
or to store it in a variable (as it is an ephemeral value and change with every command executed): exitstatus=$?
(remember to quote the variable in commands like export EXITSTATUS="$?"
.
In the return
command, the valid range of values is generally 0 to 255, but understand that values of 126 + n
are used by some shells to signal special exit status, so, the general recommendation is to use 0-125.
answered May 29 at 4:28
Isaac
6,3241633
6,3241633
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f446420%2fimplicit-return-in-bash-functions%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password