How to exclude a folder when using the mv command

This doesn't have anything to do with mv, but is a bash feature, citing man bash:

If the extglob shell option is enabled using the shopt builtin, several extended pattern matching operators are recognized. In the following description, a pattern-list is a list of one or more patterns separated by a |. Composite patterns may be formed using one or more of the following sub-patterns:

!(pattern-list)
Matches anything except one of the given patterns

!(f1) matches f2 f3 in your example, so effectively you're doing:

mv -t f3/ f2 f3 f2

To achieve your goal you should rather do:

mv -t f3/ !(f[13]) # or !(f1|f3)

This expression matches everything except f1 and f3.

This also works with *, ? and […]:

$ ls
e1  e2  e3  f1  f2  f3
$ ls !(e*|?[12])
f3

!(f1) is an extended glob expression, so (provided the extglob shell option is set) it expands to a list of (non)-matching files. In other words, if your directory originally contained f1, f2, f3 then

mv -t f3/ !(f1) f2

expands as

mv -t f3/ f2 f3 f2

The first error should be obvious; the second is because it attempts to move f2 twice - and fails the second time.