Converte o link simbólico absoluto para o link simbólico relativo com o comando Linux simples

26

Eu tenho um sub-sistema de arquivos completo dentro de um caminho /home/user/system contendo a estrutura padrão do Linux com diretórios /bin , /home , /root , /usr , /var , /etc , ...

Este sub-sistema de arquivos contém links simbólicos, relativos ou absolutos. Os links simbólicos relativos são bons, eles ficam dentro do sub-sistema de arquivos em /home/user/system . Mas os links simbólicos absolutos são problemáticos, pois apontam para um alvo fora do sub-sistema de arquivos.

Como exemplo, assumimos um symlink absoluto da seguinte forma (visto dentro do sub-filesystem):

/usr/file1 -> /usr/lib/file1

No sistema de arquivos geral, temos um link em /home/user/system/usr/file1 que agora aponta para um arquivo /usr/lib/file1 fora do sub-sistema de arquivos, em vez de um arquivo /home/user/system/usr/lib/file1 dentro do sub-sistema de arquivos.

Eu gostaria de ter um script simples, de preferência uma única linha de comando (rsync, chroot, find, ...) que converte cada link simbólico absoluto em um relativo.

No exemplo dado, esse link relativo se tornaria

/usr/file1 -> ../usr/lib/file1
    
por Alex 12.11.2013 / 17:55

4 respostas

17

Com o symlinks utility de Mark Lord (oferecido por muitas distribuições; se o seu não tiver, construa a partir da fonte ):

chroot /home/user/system symlinks -cr .

Como alternativa, em sistemas que tenham um comando readlink e um predicado -lname para find (aviso: código não testado):

cd /home/user/system &&
find . -lname '/*' -exec ksh -c '
  for link; do
    target=$(readlink "$link")
    link=${link#./}
    root=${link//+([!\/])/..}; root=${root#/}; root=${root%..}
    rm "$link"
    ln -s "$root${target#/}" "$link"
  done
' _ {} +
    
por 13.11.2013 / 01:19
0

Esse snippet do bash deve fazer isso. O primeiro formulário irá imprimir o que faria; o segundo fará isso. Eu revisaria cuidadosamente a saída, pois ela é destrutiva - o ln -f sobrescreve o link existente.

TOP=/home/user/system
cd $TOP
find * -type l -print | while read l; do echo ln -sf $TOP$(readlink $l) $l; done
find * -type l -print | while read l; do      ln -sf $TOP$(readlink $l) $l; done
    
por 28.12.2013 / 07:41
0

Aqui está uma solução sh pura.

cd /home/user/system &&
find . -lname '/*' |
while read l ; do
  echo ln -sf $(echo $(echo $l | sed 's|/[^/]*|/..|g')$(readlink $l) | sed 's/.....//') $l
done |
sh
    
por 05.03.2016 / 14:48
0

A transformação absoluta em links relativos é suportada pelo sshfs, que monta diretórios remotos via ssh.

O comando é: Lá     sudo sshfs @: // home // mntpoint / -o transform_symlinks -o allow_other

O comando, especialmente o, deve ser adaptado ao ambiente específico.

    
por 15.11.2017 / 18:44