使用简单的 Linux 命令将绝对符号链接转换为相对符号链接

Ale*_*lex 37 filesystems symlink

我在/home/user/system包含标准 Linux 结构的路径中有一个完整的子文件系统,其中包含目录/bin, /home, /root, /usr, /var, /etc,...

这个子文件系统包含符号链接,无论是相对的还是绝对的。相对符号链接很好,它们保留在/home/user/system. 但是绝对符号链接是有问题的,因为它们指向子文件系统之外的目标。

作为一个例子,我们假设一个绝对符号链接如下(在子文件系统中看到):

/usr/file1 -> /usr/lib/file1
Run Code Online (Sandbox Code Playgroud)

在整个文件系统中,我们现在有一个链接/home/user/system/usr/file1指向/usr/lib/file1子文件系统外部的文件,而不是子文件系统/home/user/system/usr/lib/file1 内部的文件。

我想要一个简单的脚本,最好是一个将每个绝对符号链接转换为相对符号链接的单个命令行(rsync、chroot、find 等)。

在给定的示例中,该相对链接将变为

/usr/file1 -> ../usr/lib/file1
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 24

使用Mark Lord的symlinks实用程序(由许多发行版提供;如果您的发行版没有,请从源代码构建):

chroot /home/user/system symlinks -cr .
Run Code Online (Sandbox Code Playgroud)

或者,在具有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
' _ {} +
Run Code Online (Sandbox Code Playgroud)


小智 5

纯 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
Run Code Online (Sandbox Code Playgroud)

你可以改变:

  • 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" - 找到相对于符号链接的目标路径,换句话说:将绝对路径转换为相对路径