I had a similar problem so I'll post my solution here.
Apparently there's not a way to avoid to span a subshell when using $(command) so the only solution that I got is to use a global variable -> pass it to the function and use eval.
My case was a bit trickier.
I wanted to open a file descriptor in a function and pass back the fd number to the main function.
The problem is that the file descriptor is opened in the subshell and not in the main:
open_fd_and_return() {
local _my_file="${1}" _my_fd_no
exec {_my_fd_no}>"${_my_file}" || die "impossible to open the fd"
echo "${_my_fd_no}"
}
my_file="$(mktemp --dry-run)"
my_fd="$(open_fd_and_return "${my_file}")"
echo "test $$" >&"${my_fd}"
rm "${my_file}"
exec {my_fd}>&-
this return "bad file descriptor error"
my solution for now is to use eval (even if uglier)
open_fd_and_return_eval() {
local _my_var="${1}"
local _my_file="${2}"
local _my_fd_no
exec {_my_fd_no}>"${_my_file}" || die "impossible to open the fd"
eval "${_my_var}=$=\${_my_fd_no}"
}
my_file="$(mktemp --dry-run)"
my_fd=""
open_fd_and_return_eval "my_fd" "${1}"
echo "test $$" >&"${my_fd}"
rm -- "${my_file}"
exec {my_fd}>&-
This works. Hopefully this is useful for someone.