我有一堆/home
指向文件和子目录的符号链接/foo
。我想定位新目录/bar
.
我的方法是查看所有无效的符号链接并验证它们是否指向/foo
.然后我做了以下事情:
sudo find . -type l -! -exec test -e {} \; -exec sh -c '\
old_link_target=$(readlink "$0"); \
new_link_target=${old_link_target//foo/bar}; \
ln -snf $new_link_target $0' {} \;
但是,我想要一种更精确的方法,该方法不包括关注无效符号链接的初始步骤。因此,对于这个问题,假设/foo
仍然存在,因此需要另一种方法。
答案1
GNUly:
find . -lname '/foo*' -printf '%p\0%l\0' |
awk -vRS='\0' '
{
getline target
sub("^/foo", "/bar", target)
printf("%s\0%s\0", target, $0)
}' |
xargs -r0n2 ln -sfT
或者使用最近的 GNU sed
:
find . -lname '/foo*' -printf '%l\0%p\0' |
sed -z 's|^/foo|/bar|;n' |
xargs -r0n2 ln -sfT
请注意,您可能会影响符号链接的所有权(例如,如果它们位于不属于他们的目录中,但具有写入权限并具有t
位设置(如/tmp
))。
为了防止这种情况,你可以使用 GNUtar
来代替:
find . -lname '/foo*' -print0 |
tar --null -T - -cf - --transform='s@^/foo@/bar@' |
tar xpf -
答案2
这是一个很小的测试集:
mkdir ./tmp1 ./tmp2
touch ./tmp1/file1 ./tmp2/file2
ln -s ./tmp1 ./tmp3
ls -H ./tmp3
输出
file1
所以现在我要...
mount --bind ./tmp2 ./tmp1
ls -H ./tmp3
输出
file2
多达!现在,所有曾经指向的链接都./tmp1
将自动指向./tmp2
- 事实上,也是如此,./tmp1
因为它们是相同的安装点。如果./tmp2
包含了我可能会做的儿童安装:
mount --rbind ./tmp2 ./tmp1
并递归地--bind
mount
编辑树。这甚至还不是 Linux 内核 vfs 的皮毛共享子树 mount
选项。
在 Linux 系统上,您不必过多关心文件指向哪个目录,因为您可以使用内核的虚拟文件系统挂载树以原子方式影响该文件的位置 - 它由您使用。您可以在 中管理整个事情/etc/fstab
。
>>/etc/fstab \
printf '%s %s none bind,defaults 0 0\n' \
"/bar" "/foo"
你的问题就解决了。