Links simbólicos de atualização em lote recursivamente


12

Eu tenho um aplicativo da web que possui vários links simbólicos em subdiretórios. Preciso mover o aplicativo para outra estrutura de diretório e atualizar todos os links simbólicos para apontar para o novo caminho. Por exemplo:

Dir antigo: Dir /home/user/public_html/dev
novo: /home/user/public_html/qa
Link simbólico antigo: /home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/dev/images
Link simbólico novo:/home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/qa/images

O problema é que existem muitos deles espalhados por vários diretórios. Como posso recursivamente pesquisar a partir da raiz e recriar todos os links simbólicos que apontam para /dev/com /qa/?

Respostas:


16

Este comando bash deve fazer isso por você:

find /home/user/public_html/qa/ -type l -lname '/home/user/public_html/dev/*' -printf 'ln -nsf "$(readlink "%p" | sed s/dev/qa/)" "$(echo "%p" | sed s/dev/qa/)"\n' > script.sh

Ele usa findpara identificar todos os arquivos no qadiretório que são links simbólicos com um destino que está no devdiretório e, para cada um, imprime um comando bash que substitui o link por um link para o caminho equivalente qa/. Depois de executar isso, basta executar o script gerado com

bash script.sh

Você pode examiná-lo manualmente primeiro para garantir que funcionou.

Aqui está uma versão mais detalhada do findcomando acima para facilitar a leitura (embora eu não necessariamente escreva dessa maneira na prática):

SRC_DIR="/home/user/public_html/qa"
OLD_TARGET="/home/user/public_html/dev"
SUB="s/dev/qa/"

find $SRC_DIR -type l \
  -lname "$OLD_TARGET/*" -printf \
  'ln -nsf "$(readlink "%p"|sed $SUB)" "$(echo "%p"|sed $SUB)"\n'\
 > script.sh

Isso cria um script.sh vazio. E executando o comando find da seguinte forma: find /home/user/public_html/qa/ -type l -lname '/home/user/public_html/dev/*' não gera nada.
— ggutenberg

Você se lembrou de mudar os caminhos para os reais no seu sistema de arquivos, certo? O que acontece se você correr apenas find /home/usr/public_html/qa/ -type l? Se isso não encontrar os links, algo muito estranho está acontecendo com seu sistema.
— David Z

Sim, " find /home/user/public_html/qa/ -type l" gera os links. Mas adicionar o parâmetro -lname não gera nada.
— ggutenberg

Na verdade, em testes adicionais, parece que isso está funcionando. Não tenho certeza do que estava fazendo de errado ontem, mas agora parece ok. Obrigado.
— ggutenberg

Estranho. Bem, se você descobrir o que estava errado, faça um comentário aqui. Estou curioso.
— David Z

5

Caso outra pessoa encontre isso ao procurar uma solução: Crie um arquivo chamado "linkmod.sh" contendo:

#!/bin/sh
PATTERN1=`echo "$2"`
PATTERN2=`echo "$3"`
LINKNAME=`echo "$1"`
OLDTARGET=`readlink "$1"`
NEWTARGET=`echo "$OLDTARGET" \
| sed -e 's/'"$PATTERN1"'/'"$PATTERN2"'/'`
echo ln -nsf "$NEWTARGET" "$LINKNAME"

e corra

find . -type l -print0 | xargs -0IX echo linkmod.sh X "pattern1" "pattern2"

Você pode usar a opção -lname para localizar, se necessário.

NOTA: você precisa usar 2x \ nos padrões antes de qualquer caractere que exija \ in sed, pois o eco remove um. Por exemplo

find . -type l -print0 | xargs -0IX echo linkmod.sh X "folder\\ name\\/file" "folder2\\ name\\/file"

Remova echoda última linha se os comandos ln estiverem corretos.


Pode ser bom para esclarecer que tanto o echona linha final do roteiro e echono find .. | xargs .. linkmod.sh ...próprio comando ambos têm de ser retirados.
— Kyle Strand

2

Criei um script bash link_rename.shpara renomear recursivamente os links simbólicos em um determinado diretório

#! /bin/bash

DIR=$1
OLD_PATTERN=$2
NEW_PATTERN=$3

while read -r line
do
    echo $line
    CUR_LINK_PATH="$(readlink "$line")"
    NEW_LINK_PATH="$CUR_LINK_PATH"  
    NEW_LINK_PATH="${NEW_LINK_PATH/"$OLD_PATTERN"/"$NEW_PATTERN"}"
    rm "$line"
    ln -s "$NEW_LINK_PATH" "$line"
done <<< $(find "$DIR" -type l)

Pode ser executado como link_rename.sh /home/human/dir link1 link2

O script possui 3 argumentos:

  1. O diretório em que você deseja executar a renomeação em lote de links simbólicos
  2. O velho padrão Aqui link1está o antigo padrão que será substituído
  3. O novo padrão. Aqui link2está o novo padrão com o qual link1será substituído

O script lê recursivamente todos os links simbólicos no diretório usando find "$DIR" -type l e processa linha por linha.

$line é o link simbólico que precisa ser renomeado

CUR_LINK_PATH é o caminho antigo

NEW_LINK_PATH é obtido executando a substituição de cadeia no caminho do link antigo.

O link simbólico antigo é removido e o novo link simbólico é criado usando ln -s "$NEW_LINK_PATH" "$line"


0

Acabei escrevendo um script PHP de linha de comando que parece fazer o truque.

<?php
//Run via command-line
$dir = new RecursiveDirectoryIterator('.');
foreach(new RecursiveIteratorIterator($dir) as $file) {
    //$link = readlink($file);
    if(is_link($file)) {
        $old_link = readlink($file);
        $new_link = str_ireplace("/joomla/", "/qa/", $old_link);
        if($new_link != $old_link) {
            exec('rm "'.$file.'"');
            exec('ln -fs "'.$new_link.'" "'.$file.'"');
            $new_link = readlink($file);
            if($new_link == $old_link) {
                echo $file."\t".$old_link."\t".$new_link."\n";
            }
        }
    }
}
?>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.