web-dev-qa-db-ja.com

単純なLinuxコマンドで絶対シンボリックリンクを相対シンボリックリンクに変換する

パス/home/user/system内に完全なサブファイルシステムがあり、ディレクトリ/bin/home/root/usr/var/etc、...

このサブファイルシステムには、相対または絶対のシンボリックリンクが含まれています。相対シンボリックリンクは問題なく、/home/user/systemの下のサブファイルシステム内にとどまります。しかし、絶対シンボリックリンクはサブファイルシステムの外部のターゲットを指すため、問題があります。

例として、絶対的なシンボリックリンクを次のように想定します(サブファイルシステム内に表示)。

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

ファイルシステム全体では、/home/user/system/usr/file1にリンクがあります。このリンクは、ファイル/usr/lib/file1insideではなく、サブファイルシステムの外部のファイル/home/user/system/usr/lib/file1を指します。

すべての絶対シンボリックリンクを相対シンボリックリンクに変換する単純なスクリプト、できれば単一のコマンドライン(rsync、chroot、find、...)が欲しいです。

与えられた例では、その相対リンクは次のようになります

/usr/file1 -> ../usr/lib/file1
29
Alex

symlinksユーティリティ によるMark Lord(多くのディストリビューションから提供されています。もしお持ちでない場合は、 source )からビルドしてください。

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
' _ {} +

純粋な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")"-symlinkターゲットへの絶対パスを検索します
  • _ln -fs_-シンボリックリンク(_-s_)を作成し、既存の(_-f_)を強制的に書き換えます
  • _realpath -s "$l"_-シンボリックリンク自体への絶対パスを検索します
  • dirname "$(realpath -s "$l")"-シンボリックリンクを含むディレクトリへの絶対パスを検索します
  • realpath --relative-to="$(dirname "$(realpath -s "$l")")" "$target"-シンボリックリンクに対するターゲットのパスを検索します。つまり、絶対パスを相対パスに変換します
4
LUMIFAZA

相対リンクでの絶対変換は、sshを介してリモートディレクトリをマウントするsshfsでサポートされています。

コマンドは次のとおりです。

Sudo sshfs <remote_user>@<remote_ip_address>:/ /home/<Host_user>/mntpoint/ -o transform_symlinks -o allow_other

コマンド、特に<placeholders>、特定の環境に適応するものとします。

1
user260694

これが純粋なshソリューションです。

 cd/home/user/system && 
 find。 -lname '/ *' | 
 while read l; do 
 echo ln -sf $(echo $(echo $ l | sed 's |/[^ /] * |/.. | g')$(readlink $ l)| sed 's/.. ... // ')$ l 
 done | 
 sh 
0
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/*"現在の作業ディレクトリ内を指す絶対リンクのみを変換することを意味します

0
kyb

このbashスニペットはそれを行う必要があります。最初のフォームはそれが何をするかを印刷します。 2番目はそれを行います。破壊的であるため、出力を慎重に確認します-ln -fは既存のリンクを上書きします。

TOP=/home/user/system
cd $TOP
find * -type l -print | while read l; do echo ln -sf $TOP$(readlink $l) $l; done
find * -type l -print | while read l; do      ln -sf $TOP$(readlink $l) $l; done
0
qneill