Além do comando find do eboix (que, da forma como está, quebra no espaço em branco, colocarei uma maneira mais segura ou duas no final), você pode usar o recurso bash do extglob :
# turn extglob on
shopt -s extglob
# move everything but the files matching the pattern
mv dir1/!(*.c) -t dir2
# If you want to exclude more patterns, add a pipe between them:
mv dir1/!(*.c|*.txt) -t dir2
Veja a página bash man para mais coisas que você pode fazer com o extglob.
Observe que isso não é recursivo e, portanto, só moverá arquivos em dir1 diretamente, não em subdiretórios. O método find é recursivo.
Comandos mais seguros find :
find dir1 ! -name '*.c' -print0 | xargs -0 mv -t dir2
find dir1 ! -name '*.c' -exec mv -t dir2 {} +
Para mais padrões, basta adicionar mais ! -name declarações:
find dir1 ! -name '*.c' ! -name '*.txt' -print0 | xargs -0 mv -t dir2
find dir1 ! -name '*.c' ! -name '*.txt' -exec mv -t dir2 {} +