Yes, using ":" also illustrate the same (or similar) behavior that I'm experiencing with my script. Using the "here" string creates the additional weirdness of showing that the temporary file content is actually "deleted", but the bash process keep the FD open. Which is quite strange since it appears to have done half the job...
Below is another difference with the "here" string construct - of course this is a very inefficient way to assign a string to a variable!!! ;-) but just used as a simple example here.
# Start a new shell to make sure there is no old FD left from previous tests
bash
unset -v TESTVAR
9<<<"test data" read -r -u 9 TESTVAR
printf "OUTPUT: $TESTVAR\n"
OUTPUT: test data
FD #9 is not left open or "deleted" here:
lsof -a -d '0-20' -p $$
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 12084 mathp 0u CHR 136,4 0t0 7 /dev/pts/4
bash 12084 mathp 1u CHR 136,4 0t0 7 /dev/pts/4
bash 12084 mathp 2u CHR 136,4 0t0 7 /dev/pts/4
Now testing with the "named" (if that's a good name to call this) FD:
unset -v TEST_FD TESTVAR
{TEST_FD}<<<"test data" read -r -u $TEST_FD TESTVAR
bash: read: TESTVAR: invalid file descriptor specification
But strangely, the TEST_FD exists and is left in the "deleted" mode:
lsof -a -d '0-20' -p $$
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 12084 mathp 0u CHR 136,4 0t0 7 /dev/pts/4
bash 12084 mathp 1u CHR 136,4 0t0 7 /dev/pts/4
bash 12084 mathp 2u CHR 136,4 0t0 7 /dev/pts/4
bash 12084 mathp 10r REG 8,1 10 1049150 /tmp/sh-thd-512950288 (deleted)
Looks like the process of dynamically assigning a FD to the FD "variable" breaks the redirection. But the FD is created and it's value did get assigned to TEST_FD:
and temporary file content deleted, but the FD not un-linked....
Doing the same thing but using 2 steps works, but you're still left with a "deleted" FD:
unset -v TEST_FD TESTVAR
: {TEST_FD}<<<"test data"
read -r -u $TEST_FD TESTVAR
printf "OUTPUT: $TESTVAR FD: $TEST_FD\n"
OUTPUT: test data FD: 11
lsof -a -d '0-20' -p $$
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 12084 mathp 0u CHR 136,4 0t0 7 /dev/pts/4
bash 12084 mathp 1u CHR 136,4 0t0 7 /dev/pts/4
bash 12084 mathp 2u CHR 136,4 0t0 7 /dev/pts/4
bash 12084 mathp 10r REG 8,1 10 1049150 /tmp/sh-thd-512950288 (deleted)
bash 12084 mathp 11r REG 8,1 10 1049151 /tmp/sh-thd-263257624 (deleted)
I think that having a common behavior for "named" vs "numbered" FD in bash would be great since obviously using dynamically assigned FD (numbers) offers some advantages when coding more complex scripts.
Also related, assigning the output of the process substitution construct to a "named" FD has the same behavior, i.e. you're left with an un-linked pipe:
unset -v TESTVAR
9< <(ls ~/t) read -r -u 9 TESTVAR
printf "OUTPUT: $TESTVAR\n"
OUTPUT: 0095.out
lsof -a -d '0-20' -p $$
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 16098 mathp 0u CHR 136,4 0t0 7 /dev/pts/4
bash 16098 mathp 1u CHR 136,4 0t0 7 /dev/pts/4
bash 16098 mathp 2u CHR 136,4 0t0 7 /dev/pts/4
unset -v TEST_FD TESTVAR
: {TEST_FD}< <(ls ~/t)
read -r -u $TEST_FD TESTVAR
printf "OUTPUT: $TESTVAR FD: $TEST_FD\n"
OUTPUT: 0095.out FD: 10
lsof -a -d '0-20' -p $$
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 16098 mathp 0u CHR 136,4 0t0 7 /dev/pts/4
bash 16098 mathp 1u CHR 136,4 0t0 7 /dev/pts/4
bash 16098 mathp 2u CHR 136,4 0t0 7 /dev/pts/4
bash 16098 mathp 10r FIFO 0,8 0t0 96683179 pipe
Thanks!
Math.