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/?

Ggutenberg
fonte

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
David Z
fonte
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.

rknC
fonte
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"

Akhil Mohan
fonte
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";
            }
        }
    }
}
?>
Ggutenberg
fonte