Com base nas respostas do @ C2H5OH e @user1277476, encontrei uma solução:
$ for file in 'find . -type l'; do link=$(readlink $file); ln -sfT ${link//gsf/msf} $file; done
Por exemplo, estou renomeando muitos arquivos dentro de uma árvore assim:
[bash]$ for file in 'find . -name "*gsf*"'; do 'mv $file ${file/gsf/msf}'; done
Isso renomeia todas as instâncias de "gsf" em nomes de arquivos que correspondem a gsf para "msf", mas os softlinks continuam apontando para arquivos agora inexistentes contendo "gsf".
Por exemplo, é isso que acontece depois da renomeação:
lrwxrwxrwx 1 trusktr users 20 Apr 25 14:39 libmsf-1.so -> libgsf-1.so.114.0.23
lrwxrwxrwx 1 trusktr users 20 Apr 25 14:39 libmsf-1.so.114 -> libgsf-1.so.114.0.23
-rwxr-xr-x 1 trusktr users 265584 Apr 21 04:41 libmsf-1.so.114.0.23
Como você pode ver, os links apontam para libgsf-1.so.114.0.23
, que não existe mais, porque foi renomeado para libmsf-1.so.114.0.23
.
O que posso fazer para que a renomeação também aconteça aos ponteiros do link de software?
Nada; isso é o que faz deles links simbólicos, você precisa lidar com eles sozinho. Os links físicos referenciam o nó de índice real ("inode") no sistema de arquivos e, portanto, permanecem válidos; é exatamente por isso que você usaria hard links em vez de links simbólicos nesse caso.
Além da explicação técnica, já respondida. Você pode alterar para onde os links simbólicos apontam:
find . -type l
ln -sfT target link_name
As opções -sfT
devem ser especificadas para reenviar links simbólicos sem surpresas.
find
e ln
são bons.
readlink
também é bom.
Desde que eu não posso adicionar um comentário, aqui está uma versão que não invoca um shell para encontrar links, evitando assim sobrecarga adicional devido a fork () e outros syscalls
for file in $(find . -type l); do
link=$(readlink $file);
ln -sfT ${link//gsf/msf} $file;
done
Isso é baseado na resposta @trusktr
Tags command-line bash linux shell