Bash does not treat the
] characters (on their own) any different from a letter of the alphabet.
In this case bash sees a "word",
[, and goes looking for a command with that name. If you look in your filesystem you'll probably find that
/usr/bin/[) exists as an executable file. As it happens, bash also provides a built in version (for the sake of efficiency), but that's just an implementation detail.
[ command (as in, the executable with that name), has a rule that the last parameter you pass to it should be
] or else it throws an error. This may be partly because it's aesthetically pleasing, but it also serves to protect you from accidentally truncated commands, which is nice.
The fact that these are not special is why you can't omit the white space before and after the
] occur in the correct format within the same word, e.g.
[a-z], then that is special and bash's globbing rules apply.
[[ command is special and can do many things
[ cannot (and parameters inside
[[ .. ]] are processed differently, as are some line breaks). The corresponding
]] is also special, as it is a shell reserved word that cannot be a command name, and terminates the special processing that follows the