/home/user/system
我在包含标准 Linux 结构的路径中有一个完整的子文件系统,其中包含目录/bin
, /home
, /root
, /usr
, /var
, /etc
,...
该子文件系统包含相对或绝对的符号链接。相对符号链接很好,它们保留在/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 .
tofind /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/*"
代表仅转换指向当前工作目录内的绝对链接