A maneira correta de fazer isso é usar a opção --no-dereference da seguinte forma.
$ ln -snf foo2 bar
Isso faz com que ln trate o link simbólico existente como um arquivo. Caso contrário, ele desreferencia bar para foo1 , desce para foo1 e usa o nome TARGET original como LINK_NAME e é por isso que você acaba com um link simbólico para foo2 sendo criado dentro da foo1 diretório. A página manpage em ln declara o seguinte ...
-n, --no-dereference
treat LINK_NAME as a normal file if it is a symbolic link to a
directory
Abaixo está a saída do shell no meu desktop Arch Linux com a versão 8.21 de ln com e sem a opção --no-dereference , obtive os mesmos resultados que você fez sem a opção --no-dereference , mas usando a opção --no-dereference funcionou como esperado.
$ mkdir foo1 foo2
$ ln -s foo1 bar
$ ls -l bar
lrwxrwxrwx 1 drew users 4 Sep 17 12:51 bar -> foo1
$ ln -sf foo2 bar
$ ls -l bar
lrwxrwxrwx 1 drew users 4 Sep 17 12:51 bar -> foo1
$ ls -l foo1
total 0
lrwxrwxrwx 1 drew users 4 Sep 17 12:51 foo2 -> foo2
$ ln -snf foo2 bar
$ ls -l bar
lrwxrwxrwx 1 drew users 4 Sep 17 12:52 bar -> foo2