If you have a scalar parameter named foo, $#foo
is the number of characters. If it's an array, $#foo
is the number of elements. The key point in my mind is that
when you assign a parameter from command substitution, e.g. foo=$(bar),
then what you get is a scalar parameter, not an array. You can
get an array instead, but you have to ask for it explicitly by
putting extra parentheses around the right hand side: foo=($(bar)).
So parameter assignment defaults to scalar mode and requires
extra punctuation to do array mode. But directly counting the
result of the substitution with no intervening parameter
defaults to array mode and requires extra punctuation to do
scalar mode.