Batch Atualizar Links Simbólicos Recursivamente

8

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

Old Dir: /home/user/public_html/dev
New Dir: /home/user/public_html/qa
Old Symlink: /home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/dev/images
Novo Symlink: /home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/qa/images

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

    
por ggutenberg 28.06.2010 / 18:11

4 respostas

12

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 find para identificar todos os arquivos no diretório qa que são links simbólicos com um destino que está no diretório dev e, para cada um, imprime um comando bash que substituirá o link por um link para o caminho equivalente em qa/ . Depois de executar isso, basta executar o script gerado com

bash script.sh

Você pode querer examiná-lo manualmente primeiro para ter certeza de que funcionou.

Aqui está uma versão mais detalhada do comando find acima para facilitar a leitura (embora eu não necessariamente escrevesse assim 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
    
por 28.06.2010 / 21:56
5

No caso de alguém mais encontrar 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 execute

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

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

NOTA: você tem que usar 2x \ nos padrões antes de qualquer caractere que exija \ in sed, já que o echo remove um. Por exemplo

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

Remova o echo da última linha se os comandos de ln estiverem corretos.

    
por 03.05.2012 / 09:54
0

Acabei de escrever 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";
            }
        }
    }
}
?>
    
por 29.06.2010 / 06:45
0

Eu criei um script bash link_rename.sh para os links simbólicos de renomeação recursiva 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 tem 3 argumentos:

  1. O diretório no qual você deseja executar a renomeação em lote de links simbólicos
  2. O padrão antigo. Aqui link1 é o padrão antigo que será substituído
  3. O novo padrão. Aqui link2 é o novo padrão com o qual link1 será 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 string no caminho do link antigo.

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

    
por 03.09.2018 / 10:08