In reading through the source to fff to learn more about Bash programming, I saw a timeout option passed to read
as an array here:
read "${read_flags[@]}" -srn 1 && key "$REPLY"
The value of read_flags
is set like this:
read_flags=(-t 0.05)
(The resulting read
invocation intended is therefore read -t 0.05 -srn 1
).
I can't quite figure out why a string could not have been used, i.e.:
read_flags="-t 0.05"
read "$read_flags" -srn 1 && key "$REPLY"
This string based approach results in an "invalid timeout specification".
Investigating, I came up with a test script parmtest
:
show() {
for i in "$@"; do printf '[%s]' "$i"; done
printf '\n'
}
opt_string="-t 1"
opt_array=(-t 1)
echo 'Using string-based option...'
show string "$opt_string" x y z
read "$opt_string"
echo
echo 'Using array-based option...'
show array "${opt_array[@]}" x y z
read "${opt_array[@]}"
Running this, with bash parmtest
($BASH_VERSION
is 5.1.4(1)-release), gives:
Using string-based option...
[string][-t 1][x][y][z]
parmtest: line 11: read: 1: invalid timeout specification
Using array-based option...
[array][-t][1][x][y][z]
(1 second delay...)
I can see from the debug output that the value of 1
in the array based approach is separate and without whitespace. I can also see from the error message that there's an extra space before the 1
: read: 1: invalid timeout specification
. My suspicions are in that area.
The strange thing is that if I use this approach with another command, e.g. date
, the problem doesn't exist:
show() {
for i in "$@"; do printf '[%s]' "$i"; done
printf '\n'
}
opt_string="-d 1"
opt_array=(-d 1)
echo 'Using string-based option...'
show string "$opt_string" x y z
date "$opt_string"
echo
echo 'Using array-based option...'
show array "${opt_array[@]}" x y z
date "${opt_array[@]}"
(The only differences are the opt_string
and opt_array
now specify -d
not -t
and I'm calling date
not read
in each case).
When run with bash parmtest
this produces:
Using string-based option...
[string][-d 1][x][y][z]
Wed Sep 1 01:00:00 UTC 2021
Using array-based option...
[array][-d][1][x][y][z]
Wed Sep 1 01:00:00 UTC 2021
No error.
I've searched, but in vain, to find an answer to this. Moreover, the author wrote this bit directly in one go and used an array immediately, which makes me wonder.
Thank you in advance.
Update 03 Sep : Here's the blog post where I've written up what I've learned so far from reading through fff
, and I've referenced this question and the great answers in it too: Exploring fff part 1 - main.
for i in "$@" do printf '[%s]' "$i"
isprintf '[%s]' "$@"
. the builtin printf prints until there's no more arguments. – jthill Sep 01 '21 at 16:32echo
, but that's a weak excuse I guess :) – qmacro Sep 01 '21 at 19:31