8

У меня есть веб-приложение, в котором есть несколько символических ссылок в подкаталогах. Мне нужно переместить приложение в другую структуру каталогов, и мне нужно обновить все символические ссылки, чтобы они указывали на новый путь. Например:

Старый каталог: /home/user/public_html/dev
Новый каталог: /home/user/public_html/qa
Старая символическая ссылка: /home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/dev/images
Новая символическая ссылка: /home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/qa/images

Проблема в том, что их много в разных каталогах. Как я могу рекурсивно искать из корня и воссоздать все символические ссылки, указывающие на /dev/ with /qa/?

4 ответа4

12

Эта команда bash должна сделать это за вас:

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

Он использует find для идентификации всех файлов в каталоге qa которые являются символическими ссылками, с целью, находящейся в каталоге dev , и для каждого из них выводит команду bash, которая заменит ссылку ссылкой на эквивалентный путь в qa/ , После этого просто запустите сгенерированный скрипт с

bash script.sh

Возможно, вы захотите сначала проверить его вручную, чтобы убедиться, что он работает.

Вот более подробная версия приведенной выше команды find для более удобного чтения (хотя на практике я не обязательно писал бы ее так):

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
5

Если кто-то еще находит это при поиске решения: создайте файл с именем «linkmod.sh», содержащий:

#!/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"

и беги

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

При необходимости вы можете использовать опцию -lname в find.

ПРИМЕЧАНИЕ: вы должны использовать 2x \ в шаблонах перед любыми символами, которые требуют \ in sed, так как echo удаляет один. Например

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

Уберите echo из последней строки, если команды ln верны.

0

Я закончил тем, что написал сценарий PHP командной строки, который, кажется, делает свое дело.

<?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";
            }
        }
    }
}
?>
0

Я создал bash-скрипт link_rename.sh для рекурсивного переименования символических ссылок в данном каталоге

#! /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)

Это может быть выполнено как link_rename.sh /home/human/dir link1 link2

Скрипт имеет 3 аргумента:

  1. Каталог, в котором вы хотите выполнить пакетное переименование символических ссылок
  2. Старый шаблон. Здесь link1 - старый шаблон, который будет заменен
  3. Новый шаблон. Здесь link2 - это новый шаблон, которым будет заменен link1

Сценарий рекурсивно читает все символические ссылки в каталоге, используя find "$DIR" -type l и обрабатывает их построчно.

$line - это символическая ссылка, которую нужно переименовать

CUR_LINK_PATH - старый путь

NEW_LINK_PATH получается путем замены строки в старом пути ссылки.

Старая символическая ссылка удаляется, а новая символическая ссылка создается с помощью ln -s "$NEW_LINK_PATH" "$line"

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .