Checking if current file is being sourced is being reversed if $? is 0

Multi tool use


Checking if current file is being sourced is being reversed if $? is 0
I know the title is a bit weird, but I'm not sure how to better word it.
I'm using $(return &> /dev/null)
to detect if a file is sourced or not.
$(return &> /dev/null)
I know that this method is not 100% reliable, but it has worked for me without issues before now. I've figured out how to work around the problem, but I can't figure out why this is happening.
I've tried this on three different systems and had the same results:
Redhat 6.9; $BASH_VERSION=4.1.2(1)-release
Mint 18.2; $BASH_VERSION=4.3.48(1)-release
Arch; $BASE_VERSION=4.4.23(1)-release
If $?
is 1 (false) when $(return &> /dev/null)
the return code is reversed.
$?
$(return &> /dev/null)
$ hr | cat test_0source - test_0source.sh; hr; ./test_0source
#!/bin/bash
# test_0source
false
test_0source.sh
false
source test_0source.sh
true
test_0source.sh
true
source test_0source.sh
========================================
#!/bin/bash
# test_0source.sh
# shellcheck disable=SC2091
$(return &> /dev/null)
echo "$?"
========================================
1
1
1
0
I expected to be seeing
1
0
1
0
My workaround is to add true
right before the return
check. While this gives me the correct results, adding false
instead of true
cause the return
check to always return 1.
true
return
false
true
return
I realize I'm missing something basic here, but I'm not seeing it. Why is this doing this?
Edit: I had an incorrect value for $? in my initial explanation above.
[[ "${BASH_SOURCE}" = ${0} ]]
0
1
bash
1 Answer
1
What you are doing is basically "abusing" the fact that return can only happen from function or a sourced script and assuming it yields 0
when a return was possible (we're sourced) and 1
if not, while suppressing the error output. You also do that in a subshell. Oddly enough, bash is still OK with placement of the return
but does not return from a sourced script and keeps going. So far, so god.
0
1
return
The problem is, that "naked" (w/o explicit value specified) return
, just like exit
propagate last seen return code (return code of the command immediately preceding it).
return
exit
In other words false; return
would be the same thing as return 1
. You can also try this out by replacing true
and false
by (exit 255)
and see what happens.
false; return
return 1
true
false
(exit 255)
TL;DR for this construct to work as you expected, change it to return 0
.
return 0
I hope I have not missed some corner case, but this should work as an alternative with bash by comparing name of the executed script and a source file. [[ "${BASH_SOURCE}" = ${0} ]]
evaluates to 0
if file has not been sourced and 1
if it has. Or replace =
with !=
to get same meaning of values as in the return
case above.
[[ "${BASH_SOURCE}" = ${0} ]]
0
1
=
!=
return
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
May I interest you in an alternative method?
[[ "${BASH_SOURCE}" = ${0} ]]
evaluates to0
if file is not source and1
if it is (test for not equal if you prefer it the other way around). Should run onbash
pretty much anywhere.– Ondrej K.
30 mins ago