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.echo, but that's a weak excuse I guess :)