Existe uma maneira fácil de substituir todos os links simbólicos pelo arquivo ao qual eles vinculam?
Existe uma maneira fácil de substituir todos os links simbólicos pelo arquivo ao qual eles vinculam?
Respostas:
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 {} +
"$var"
para "${var}"
é um noop no sh / bash. Eu removi o bashism ( [[
), o resto é compatível com o POSIX sh.
cp
em um arquivo temporário no mesmo diretório e depois em mv -f
um arquivo temporário no original. Isso deve evitar problemas, como pessoas pressionando Ctrl-C
ou o sistema de arquivos sendo preenchido entre os comandos rm
e cp
(impedindo assim mesmo o ln
funcionamento do novo ). Os nomes de arquivos temporários são fáceis de localizar ls -a
para limpeza posterior, se necessário.
abstarget=$(readlink -f "$link")
o bloco de casos , mas pode ter sido por razões de portabilidade.
Pode ser mais fácil usar o 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
tar -hcf - sourcedir | tar -xf - -C newdir
cp -L
é a solução mais simples
cp
implementações copiarão diretórios.
Se eu entendi corretamente, a -L
bandeira do cp
comando deve fazer exatamente o que você deseja.
Basta copiar todos os links simbólicos e eles serão substituídos pelos arquivos para os quais eles apontam.
cp -L files tmp/ && rm files && cp tmp/files .
Se você esclarecer, você provavelmente vai ajudar mais pessoas ...
"fácil" será uma função sua, provavelmente.
Provavelmente eu escreveria um script que usa o utilitário de linha de comando "find" para encontrar arquivos simbolicamente vinculados e depois chama rm e cp para remover e substituir o arquivo. Você provavelmente faria bem em também chamar a ação pela verificação de localização, para que haja 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 oculte os links sym (como o samba) e, em seguida, copie tudo disso. Mas, em muitos casos, algo assim introduziria outros problemas.
Uma resposta mais direta à sua pergunta é provavelmente "sim".
Editar: conforme a solicitação de informações mais específicas. De acordo com a página de manual do find , este comando listará todos os arquivos de links sym em uma profundidade de 2 diretórios, em /:
find / -maxdepth 2 -type l -print
Para conseguir encontrar para executar algo em encontrá-lo:
find / -maxdepth 2 -type l -exec ./ReplaceSymLink.sh {} \;
Acredito que isso chamará algum script que acabei de inventar e passará o nome do arquivo que você acabou de encontrar. Como alternativa, você pode capturar a saída find para o arquivo (use "find [blah]> symlinks.data", etc) e depois passe esse arquivo para um script que você escreveu para lidar com a cópia do original normalmente.
-exec ./ReplaceSymLink.sh {} \;
Este é o oneliner que eu 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.
para f em *; do cp --remove-destination source / $ f $ f; feito
Espero que isto ajude
find . -type l -exec cp --dereference --recursive '{}' '{}'.dereferenced \;
Ele fará uma cópia de cada arquivo / pasta com link simbólico <filename>.dereferenced
, o que é mais seguro (se menos conveniente) do que apenas substituí-los diretamente. Mover os dados copiados para os nomes dos arquivos dos links simbólicos é deixado como um exercício para o leitor.
find ./ -type l -print0|xargs -0 -n1 -i sh -c 'cp --remove-destination $(readlink "{}") "{}" '
baseado em https://superuser.com/a/1301199/499386 da MastroGeppetto
Muitas respostas boas 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
Eu tive o mesmo problema com o gwenview ao copiar links quando você normalmente espera que ele siga o link e copie o arquivo.
O que 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 inicial, executar 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 foi corrigido o meu problema.
for f in *; do cp --remove-destination $(readlink "$f") "$f"; done
Eu fiz uma versão em uma linha, pois o meu hotel na web não permitia bash-scripts e funcionou 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