Because that's not what it does. You are creating two quoted strings "python2 --version; "
and "python3 --version; "
neither of which is a valid command. You could get around that with eval
but ... that way lies madness.
# XXX DON'T
eval python{2,3}" --version;"
2.7.18
Python 3.8.10
The (not so) simple but straightforward solution would be something like
for v in 2 3; do
python$v --version
done
or if you are hellbent on using a wildcard, run a subshell:
echo python{2,3}" --version;" | bash
Perhaps notice the (lack of) difference between
echo python2" --version; "
and
echo "python2 --version; "
The quotes simply tell the shell to keep things together as a single string. (For what it's worth, the shell removes the quotes as part of its parsing process, so the argument to echo
does not contain any actual quotes, just the parsed string from between the quotes.)
It's possible to have command names with literal spaces in them, but incredibly cumbersome; so you don't see this much in practice.
For fun, maybe try
# Have a directory in your PATH which is in your home directory
# If you don't, maybe create $HOME/bin and add it to your PATH
bash$ echo "$PATH" | tr ':' '\n' | grep "$HOME"
/users/you/bin
bash$ cat >"$HOME/bin/python2 --version"
#!/bin/sh
exec python2 --version
^D
bash$ chmod +x "$HOME/bin/python2 --version"
bash$ "python2 --version"
2.7.18
(Maybe delete the script when you're done experimenting.)