Substituir Links Simbólicos por Arquivos

26

Existe uma maneira fácil de substituir todos os links simbólicos pelo arquivo ao qual eles se conectam?

    
por Marty Trenouth 28.06.2011 / 21:44

12 respostas

11

Para algumas definições de "fácil":

#!/bin/sh
set -e
for link; do
    test -h "$link" || continue

    dir=$(dirname "$link")
    reltarget=$(readlink "$link")
    case $reltarget in
        /*) abstarget=$reltarget;;
        *)  abstarget=$dir/$reltarget;;
    esac

    rm -fv "$link"
    cp -afv "$abstarget" "$link" || {
        # on failure, restore the symlink
        rm -rfv "$link"
        ln -sfv "$reltarget" "$link"
    }
done

Execute este script com nomes de links como argumentos, por exemplo, através de find . -type l -exec /path/tos/script {} +

    
por 28.06.2011 / 22:36
17

Pode ser mais fácil simplesmente usar tar para copiar os dados para um novo diretório.

-H      (c and r mode only) Symbolic links named on the command line will
        be followed; the target of the link will be archived, not the
        link itself.

Você poderia usar algo assim

tar -hcf - sourcedir | tar -xf - -C newdir

tar --help:
-H, --format=FORMAT        create archive of the given format
-h, --dereference          follow symlinks; archive and dump the files they point to
    
por 28.06.2011 / 21:54
11

Se eu entendi corretamente, o sinalizador -L do comando cp deve fazer exatamente o que você deseja.

Copie todos os links simbólicos e os substituirá pelos arquivos para os quais eles apontam.

    
por 09.04.2013 / 09:57
5

"fácil" será uma função sua, provavelmente.

Eu provavelmente escreveria um script que usasse o utilitário de linha de comando "find" para encontrar arquivos simbolicamente vinculados e, em seguida, chamaria rm e cp para remover e substituir o arquivo. Você provavelmente faria bem em também ter a ação chamada por find verifique se ainda há espaço livre suficiente antes de mover o link sym também.

Outra solução pode ser montar o sistema de arquivos em questão através de algo que esconda os links sym (como o samba), então copie tudo disso. Mas em muitos casos, algo assim introduziria outros problemas.

Uma resposta mais direta à sua pergunta provavelmente é "sim".

Editar: conforme o pedido de informações mais específicas. De acordo com a página man do find , este comando listará todos os arquivos de link sym em uma profundidade de 2 diretórios, de /:

find / -maxdepth 2 -type l -print

( isso foi encontrado aqui )

Para obter informações sobre como executar algo ao encontrá-lo:

find / -maxdepth 2 -type l -exec ./ReplaceSymLink.sh {} \;

Acredito que vou chamar um script que acabei de inventar e passar o nome do arquivo que você acabou de encontrar. Alternativamente, você pode capturar a saída find para o arquivo (use "find [blah] > symlinks.data", etc) e então passar esse arquivo para um script que você tenha escrito para manipular a cópia sobre o original normalmente.

    
por 28.06.2011 / 21:48
2
find . -type l -exec cp --dereference --recursive '{}' '{}'.dereferenced \;

Será feita uma cópia de cada arquivo / pasta com link simbólico em <filename>.dereferenced , o que é mais seguro (se menos conveniente) do que simplesmente substituí-los diretamente. Mover os dados copiados para os nomes de arquivos dos links simbólicos é deixado como um exercício para o leitor.

    
por 28.06.2011 / 22:46
2

Usando algumas das ideias anteriores, o comando a seguir substituirá recursivamente cada link simbólico por uma cópia do original:

find . -type l -exec bash -c "echo 'Replacing {} ...';  cp -LR '{}' '{}'.dereferenced;  rm '{}';  mv '{}'.dereferenced '{}'" \;
    
por 25.07.2016 / 13:00
1

Muitas boas respostas lá, mas eu desde que você estava procurando por algo fácil

for i in *; do link=$(readlink $i) && rm $i && mv $link $i; done
    
por 17.02.2012 / 08:46
1

Eu tive o mesmo problema com o gwenview de copiar links quando você normalmente espera que ele siga o link e copie o arquivo.

O que eu fiz para 'limpar' o diretório seguindo todos os links e copiando todos os arquivos apontados para o diretório, foi criar um diretório de rascunho, executado por exemplo.

"for file in 'ls'; do cp -L $file scratchdir/$file; done; mv scratchdir/* ./" 

isso é muito perigoso para colocar em um script, pois não há verificação, mas resolveu o problema.

    
por 22.05.2013 / 02:55
1

Este é o oneliner que usei: suponha que todos os arquivos locais sejam links para outro arquivo em "source". Você pode refinar a seleção de arquivos com padrões ou "localizar". Por favor, entenda antes de usar.

for f in *; do cp --remove-destination source/$f $f; done

Espero que isso ajude

    
por 07.03.2018 / 11:11
1
find ./ -type l -print0|xargs -0 -n1 -i sh -c 'cp --remove-destination $(readlink "{}") "{}" '

com base no link do MastroGeppetto

    
por 08.06.2018 / 05:43
1
for f in *; do cp --remove-destination $(readlink "$f") "$f"; done
    
por 10.07.2018 / 08:00
0

Eu fiz uma versão de uma linha, já que meu web-hotel não permitia scripts bash e funcionava bem para mim:

before:
> find . -type l | wc -l
358

> for link in 'find . -type l' ; do echo "$link : "; ls -al $link ; cp $link notalink; unlink $link; mv notalink $link ; ls -al $link; done
...

after:
> find . -type l | wc -l
0
    
por 25.07.2017 / 22:54

Tags