En primer lugar, tenga en cuenta que cuando se dice esto:
BAR=$(basename $FOO) # result is BAR="baz"
BAZ=${BAR:0:1} # result is BAZ="b"
el primer bit en la construcción de BAZ
es BAR
y no el valor que desea tomar el primer carácter de. Entonces, incluso si bash permitiera que los nombres de las variables contengan caracteres arbitrarios, su resultado en la segunda expresión no sería lo que usted desea.
Sin embargo, en cuanto a la regla de que está impidiendo esto, permítanme citar desde la página de manual de bash:
DEFINITIONS
The following definitions are used throughout the rest of this docu‐
ment.
blank A space or tab.
word A sequence of characters considered as a single unit by the
shell. Also known as a token.
name A word consisting only of alphanumeric characters and under‐
scores, and beginning with an alphabetic character or an under‐
score. Also referred to as an identifier.
A continuación, un poco más tarde:
PARAMETERS
A parameter is an entity that stores values. It can be a name, a num‐
ber, or one of the special characters listed below under Special Param‐
eters. A variable is a parameter denoted by a name. A variable has a
value and zero or more attributes. Attributes are assigned using the
declare builtin command (see declare below in SHELL BUILTIN COMMANDS).
Y más tarde, cuando se define la sintaxis estás preguntando por:
${parameter:offset:length}
Substring Expansion. Expands to up to length characters of
parameter starting at the character specified by offset.
lo que las reglas como se establece en la página de manual dice que el ${foo:x:y}
constructo debe tener un parámetro como la primera parte, y que un parámetro solo puede ser un nombre, un número o uno de los pocos caracteres de parámetros especiales. $(basename $FOO)
no es una de las posibilidades permitidas para un parámetro.
En cuanto a una manera de hacer esto en una tarea, use una tubería para otros comandos como se menciona en otras respuestas.