Ok, so, as I stated in the comments above, I don't know specifically about *bash's `set -E`*, but I know that POSIX compatible shells provide a simple means of testing a value if you desire it:
sh -cevx '
_test() { echo $( ${empty:?error string} ) &&\
echo "echo still works"
}
_test && echo "_test doesnt fail"
'
sh: line 1: empty: error string
+ echo
+ echo 'echo still works'
echo still works
+ echo '_test doesnt fail'
_test doesnt fail
Above you'll see that though I used *`parameter expansion`* to test *`${empty?} _test()`* still *`return`s* a pass - as is evinced in the last *`echo`* This occurs because the failed value kills the *`$( command substitution )`* subshell that contains it, but its parent shell - *`_test`* at this time - keeps on trucking. And *`echo`* doesn't care - it's plenty happy to serve only a *`\newline; echo`* is ***not*** a test.
But consider this:
sh -cevx '
_test() { echo $( ${empty:?error string} ) &&\
echo "echo still works" ; } 2<<-INIT
${empty?function doesnt run}
INIT
_test ||\
echo "this doesnt even print"
'
_test+ sh: line 1: empty: function doesnt run
Because I fed *`_test()'s`* input with a pre-evaluated parameter in the *`INIT here-document`* now the *`test()`* function doesn't even attempt to run at all. What's more the *`sh`* shell apparently gives up the ghost entirely and *`echo "this doesnt even print"` **doesn't even print.***
Probably that is ***not*** what you want.
This happens because the *`${var?}`* style parameter-expansion is ***designed to quit the `shell`*** in the event of a missing parameter, it [works like this][1]:
> ***`${parameter:?[word]}`***
>> Indicate Error if **`Null`** or **`Unset.`** If parameter is unset or null, the *`expansion of word`* (or a message indicating it is unset if word is omitted) shall be *`written to standard error`* and the ***`shell exits with a non-zero exit status`.*** Otherwise, the value of *`parameter shall be substituted`.* An interactive shell need not exit.
I won't copy/paste the entire document, but if you want a failure for a **`set but null`** value you use the form:
> *`${var` **:?** `error message }`*
With the *`:colon`* as above. If you want a *`null`* value to succeed, just omit the colon. You can also negate it and fail only for set values, as I'll show in a moment.
Another run of *`_test():`*
sh -c '
_test() { echo $( ${empty:?error string} ) &&\
echo "echo still works" ; } 2<<-INIT
${empty?function doesnt run}
INIT
echo "this runs" |\
( _test ; echo "this doesnt" ) ||\
echo "now it prints"
'
this runs
sh: line 1: empty: function doesnt run
now it prints
This works with all kinds of quick tests, but above you'll see that *`_test()`*, run from the middle of the *`pipeline`* fails, and in fact its containing *`command list`* subshell fails entirely, as none of the commands within the function run nor the following *`echo`* run at all, though it is also shown that it can easily be tested because *`echo "now it prints"` **now prints.***
And it may not be obvious, but if you wanted to only pass for the opposite case, it's fairly simple as well:
N= #N is NULL
v=something_you_would_rather_do_without
${v+${N:?you just nest it a little}} : && some other things
And I guess we should show it work, right? We just declare it as a parameter to our function (or any time beforehand):
sh -c '
_test() { echo $( echo ${empty:?error string} ) &&\
echo "echo still works" ; } 2<<-INIT
${empty?function doesnt run}
INIT
echo "this runs" >&2 |\
( empty=not_empty _test ; echo "yay! I print now!" ) ||\
echo "suspiciously quiet"
'
this runs
not_empty
echo still works
yay! I print now!
It should be noted that this evaluation stands alone - it requires no additional test to fail. A couple more examples:
sh -c '
empty=
${empty?null, no colon, no failure}
unset empty
echo "${empty?this is stderr} this is not"
'
sh: line 3: empty: this is stderr
sh -c '
_input_fn() { set -- "$@" #redundant
echo ${*?WHERES MY DATA?}
#echo is not necessary though
shift
${*?WHERES MY DATA?}
}
_input_fn heres some stuff
_input_fn one #here
#shell dies - third try doesnt run
_input_fn you there?
'
heres some stuff
sh: line 4: some: command not found
one
sh: line 4: *: WHERES MY DATA?
[1]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02