간단한 Linux 명령을 사용하여 절대 심볼릭 링크를 상대 심볼릭 링크로 변환

간단한 Linux 명령을 사용하여 절대 심볼릭 링크를 상대 심볼릭 링크로 변환

/home/user/system/bin, /home, /root, /usr, /var, /etc... 디렉토리를 포함하는 표준 Linux 구조를 포함하는 경로에 완전한 하위 파일 시스템이 있습니다.

이 하위 파일 시스템에는 상대 또는 절대 기호 링크가 포함되어 있습니다. 상대 심볼릭 링크는 괜찮습니다 /home/user/system. 그러나 절대 심볼릭 링크는 서브파일 시스템 외부의 대상을 가리키기 때문에 문제가 있습니다.

예를 들어, 다음과 같은 절대 심볼릭 링크를 가정해 보겠습니다(하위 파일 시스템 내부에서 볼 수 있음).

/usr/file1 -> /usr/lib/file1

파일 시스템 전체에 이제 파일 대신 하위 파일 시스템 외부의 파일을 /home/user/system/usr/file1가리키는 링크가 있습니다./usr/lib/file1/home/user/system/usr/lib/file1 ~에하위 파일 시스템.

나는 모든 절대 심볼릭 링크를 상대 심볼릭 링크로 변환하기 위해 간단한 스크립트, 바람직하게는 명령줄(rsync, chroot, find, ...)을 원합니다.

주어진 예에서 이 상대 링크는 다음과 같습니다.

/usr/file1 -> ../usr/lib/file1

답변1

와 함께symlinks유용Mark Lord 작성(많은 배포판에서 사용 가능. 배포판이 그렇지 않은 경우원천):

chroot /home/user/system symlinks -cr .

readlink-lname또는 명령과 조건자가 있는 시스템에서 find(경고: 테스트되지 않은 코드):

cd /home/user/system &&
find . -lname '/*' -exec ksh -c '
  for link; do
    target=$(readlink "$link")
    link=${link#./}
    root=${link//+([!\/])/..}; root=${root#/}; root=${root%..}
    rm "$link"
    ln -s "$root${target#/}" "$link"
  done
' _ {} +

답변2

순수 bash 및 coreutils, ../경로에 불필요한 s 없이 심볼릭 링크를 상대 경로로 변경합니다.

find . -type l | while read l; do
    target="$(realpath "$l")"
    ln -fs "$(realpath --relative-to="$(dirname "$(realpath -s "$l")")" "$target")" "$l"
done

다음을 변경할 수 있습니다.

  • find .find /path/to/directory이 디렉토리의 심볼릭 링크를 변환 하려면
  • ln -fs테스트 echo ln -fs실행 수행

설명하다:

  • target="$(realpath "$l")"- 심볼릭 링크 대상의 절대 경로 찾기
  • ln -fs- 심볼릭 링크 생성( -s), 강제( -f)로 기존 링크 덮어쓰기
  • realpath -s "$l"- 심볼릭 링크 자체의 절대 경로 찾기
  • dirname "$(realpath -s "$l")"- 심볼릭 링크가 포함된 디렉토리의 절대 경로 찾기
  • realpath --relative-to="$(dirname "$(realpath -s "$l")")" "$target"- 심볼릭 링크를 기준으로 대상의 경로를 찾습니다. 즉, 절대 경로를 상대 경로로 변환합니다.

답변3

sshfs는 상대 링크의 절대값 변환을 지원하며 SSH를 통해 원격 디렉터리를 마운트합니다.

명령은 다음과 같습니다. 예

sudo sshfs <remote_user>@<remote_ip_address>:/ /home/<host_user>/mntpoint/ -o transform_symlinks -o allow_other

명령, 특히 명령은 <placeholders>특정 상황에 맞게 조정되어야 합니다.

답변4

find -lname "$PWD/*" | while read link ;do  
   target=$(readlink $link);
   relative_target=$(realpath $target --relative-to=$link/.. --no-symlinks --canonicalize-missing);
   ln --force --symbolic --no-target-directory $relative_target $link
done

"$PWD/*"현재 작업 디렉토리를 가리키는 절대 링크 변환만 나타냅니다.

관련 정보