Skip to main content
Better not to expand things that don't need to be expanded in what's passed to `eval`.
Source Link
Stéphane Chazelas
  • 584.6k
  • 96
  • 1.1k
  • 1.7k

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.

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}"

    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}"

    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.

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.

Source Link

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}"

    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}"

    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.