While it is probably useful to have every place where expansions occur list which ones apply, perhaps it would (also) be useful to include the general principle which controls all of this.
That is, expansions are performed, late (just as commands are about to be run, after all parsing has finished, etc) in one of two basic contexts. In one, like in arg lists to commands (also the list after "in" in a for statement, and probablty more places I have forgotten), any number of words can be produced. In those, all the expansions typically happen. In the other, exactly one word is required - like the word in var=${word} or the word in case ${word} in, or (in bash, and perhaps a couple of other shells) the word after a here string operator <<<${word} (and one more I will come to in a minute). [The word after a here-doc redirect operator (<<) is strange for hysterical (oops: historical) reasons.] In those, the syntax allows for only one word to be produced, so performing field splitting, globbing, or brace expansion, all make no sense at all, and so the basic assumption, unless specified otherwise, is that none of those will happen. (This is also why var="$@" is just plain stupid to write, and has unspecified consequences, though people keep doing it). quote removal always happens (everywhere). The one other place where just one word is required, and is all that makes sense, is after a redirect operator - the file name (or fd if the operator is >& or similar). That is >${word} (etc). For most shells none of the multi-word generating "expansions" happen there either, as there has to be exactly one filename to write into (in this example), not several. However, at least when interactive, some shells perform globbing at this point, but require that only a single filename match the pattern (making it an error if more than one do) - just because users are too lazy to type the entire filename -- or use a func like: setfn() { var=$1; shift set -- "$@" case "$#" in 1) test -e "$1" && { eval "$var='$1'" return 0 } printf >&2 'No match\n' return 1; ;; esac printf >&2 'Ambiguous: %d files matched\n', "$#" return 1 } Used like setfn f a*.txt after which, if it worked, you can use "$f" instead of the filename you are too lazy to type, which is shorter than a pattern guaranteed to only match one file will often be. Further it doesn't risk failing later, if something you do causes the pattern to later match more than one file (say you create abc-new.txt as a new version of abc.txt or save the old one as abc.was.txt). "$f" doesn't change until you change it. Bash allows filename expansion after a redirect, at least in interactive shells (haven't tested it for non-interactive), it also performs brace expansion there - but that's largely guaranteed to fail, so I have no idea why - no field splitting though. Those exceptions to the general rule need to be clearly pointed out, but explaining every time something requires just one word, that some expansions don't happen, when in a context where it would be insane if they did, seems overdone. <<< requires a single word, as so all other redirect operators. Brace expansion, which has as its whole purpose, generating multiple words (as does field splitting, though it doesn't always succeed) (globbing merely can) should be obviously inappropriate there (just as it really should be after any redirect operator, which is why I was surprised to see $ cat < a{1,2,3} -bash: a{1,2,3}: ambiguous redirect rather than something more like -bash: a{1,2,3}: No such file or directory The only example of brace expansion actually "working" in a redirect, is something like $ cat <a{1..1} -bash: a1: No such file or directory but I am unable to think of any situation where doing that is better than just "cat <a1". Even if the 1's were variables being expanded, we know that either they have the same value, in which case we only need to use one of them <a${var} or they're different, in which case we get an "ambiguous redirect error". Crazy. kre