我喜欢尽可能使用相对符号链接,因为即使我的文件系统安装在非根位置,例如,如果我是远程访问它。
但是,如果我移动包含相对符号链接的目录,通常这些链接将变得无效。
我正在寻找一个可用于移动整个目录(树)的命令,仅重写那些指向目录外部的相对符号链接,以便它们仍然指向相同的文件。
Stack Overflow 上有一个相关问题,如何移动相对符号链接?。另外,在 Unix 和 Linux 上,查找目录树中指向该树外部的所有符号链接,并且(指的是一个更难的问题)是否有某种符号链接支持移动或重命名目标文件?。
例如,一个名为mv-rel
which 的命令的行为如下(其他命令是其 GNU coreutils 版本):
$ mkdir foo
$ touch bar
$ ln -sr bar foo/
$ touch foo/flob
$ ln -sr foo/flob foo/qux
$ ls -gG foo/
total 0
lrwxrwxrwx 1 6 Dec 1 00:05 bar -> ../bar
-rw-r--r-- 1 0 Dec 1 00:24 flob
lrwxrwxrwx 1 4 Dec 1 00:24 qux -> flob
$ mkdir baz
$ mv-rel foo/ baz
$ ls -gG baz/foo/
total 0
lrwxrwxrwx 1 6 Dec 1 00:05 bar -> ../../bar
-rw-r--r-- 1 0 Dec 1 00:24 flob
lrwxrwxrwx 1 4 Dec 1 00:24 qux -> flob
除非我遗漏了一些东西,否则这似乎也是“mv”命令(也可能是“cp”)的有用命令行选项。但出于这个问题的目的,我正在寻找现在存在的东西,或者实现此功能的简单可移植脚本。
答案1
我最终写了一个解决方案并将其发布到Github上:
https://github.com/minTaqa/mvrel
它目前不像“mv”那么灵活,因为只允许两个参数,并且第二个参数必须是目录。但是,我发现它对于移动具有大量相对符号链接的内容很有用。我想确保它可以处理文件名中的空格、换行符和其他乱七八糟的内容,因此这也是我了解 Bats 的一个机会,Bats 是用 Bash 编写的符合 TAP 的测试框架,我在其中进行了一些单元测试说服自己一切正常。
脚本本身也是用 Bash 编写的。我认为这对于这项任务来说是最简单、最可移植的语言,但最终我不得不解决以下问题:命令替换删除尾随换行符(如果你的文件名带有尾随换行符,这是一个问题,这主要是理论上的,但仍然很烦人)。然后有find ... -print0
并且IFS= read -rd ''
,加上大量的引号和“--”参数——在 Perl 等稍低级的脚本语言中不需要这些东西。我也不会做通过参数扩展进行字符串操作在 Perl 中。不管怎样,如果你愿意的话,你可以用 Perl 甚至 C 重写它;事实上,它在 Bash 中相当短。
答案2
这是一个相当具有破坏性的方法:用绝对链接替换相对链接:
cd foo
for f in *; do
if [[ -h $f ]] # True if file is a symbolic link.
then
abs=$(readlink -f "$f") && rm "$f" && ln -s "$abs" "$f"
fi
done