재귀 적으로 일괄 업데이트 심볼릭 링크


13

하위 디렉토리에 많은 심볼릭 링크가있는 웹 응용 프로그램이 있습니다. 앱을 다른 디렉토리 구조로 이동해야하며 새 경로를 가리 키도록 모든 심볼릭 링크를 업데이트해야합니다. 예를 들면 다음과 같습니다.

Old Dir : /home/user/public_html/dev
새로운 Dir : /home/user/public_html/qa
Old Symlink : /home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/dev/images
새로운 Symlink :/home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/qa/images

문제는 다양한 디렉토리에 많은 것들이 흩어져 있다는 것입니다. 루트에서 재귀 적으로 검색하고로 가리키는 모든 심볼릭 링크를 다시 만들려면 어떻게 /dev/해야 /qa/합니까?

답변:


17

이 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모든 파일을 식별하는 데 사용 되며 각 파일에 대해 링크를 해당 경로의 링크로 대체하는 bash 명령을 인쇄합니다 . 이것을 실행 한 후 생성 된 스크립트를qadevqa/

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

이것은 빈 script.sh를 만듭니다. 그리고 find 명령을 실행하면 find /home/user/public_html/qa/ -type l -lname '/home/user/public_html/dev/*' 아무것도 출력되지 않습니다.
ggutenberg

파일 시스템의 실제 경로를 변경하는 것을 기억 했습니까? 당신이 그냥 실행하면 어떻게됩니까 find /home/usr/public_html/qa/ -type l? 링크가 발견되지 않으면 시스템에서 매우 이상한 일이 발생하는 것입니다.
David Z

예, " find /home/user/public_html/qa/ -type l"링크를 출력합니다. 그러나 -lname 매개 변수를 추가하면 아무것도 출력되지 않습니다.
ggutenberg 2016 년

실제로, 추가 테스트에서 이것이 작동하는 것처럼 보입니다. 어제 내가 뭘 잘못했는지 모르겠지만 지금은 괜찮아 보입니다. 감사.
ggutenberg 2016 년

응, 이상해 글쎄, 당신이 무슨 일이 있었는지 알아내는 경우 여기에 의견을 적어주세요. 궁금해.
David Z

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 옵션을 사용할 수 있습니다.

참고 : echo는 하나를 제거하므로 sed에서 \를 필요로하는 문자보다 먼저 패턴에 2x \를 사용해야합니다. 예를 들어

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

echoln 명령이 올바른 경우 마지막 행에서를 제거 하십시오.


모두 명확히하는 것이 좋을 것 echo의 마지막 줄에서 스크립트echo에서 find .. | xargs .. linkmod.sh ...명령 자체 필요가 제거 될 수 있습니다.
Kyle Strand

2

link_rename.sh주어진 디렉토리에서 재귀 적으로 이름을 바꾸는 심볼릭 링크에 대한 bash 스크립트 를 만들었습니다.

#! /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 이전 링크 경로에서 문자열 대체를 수행하여 얻습니다.

이전 symlink가 제거되고 다음을 사용하여 새 symlink가 작성됩니다. ln -s "$NEW_LINK_PATH" "$line"


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";
            }
        }
    }
}
?>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.