将包含相对符号链接的目录移动到目录外的文件的一个好命令是什么?

将包含相对符号链接的目录移动到目录外的文件的一个好命令是什么?

我喜欢尽可能使用相对符号链接,因为即使我的文件系统安装在非根位置,例如,如果我是远程访问它

但是,如果我移动包含相对符号链接的目录,通常这些链接将变得无效。

我正在寻找一个可用于移动整个目录(树)的命令,仅重写那些指向目录外部的相对符号链接,以便它们仍然指向相同的文件。

Stack Overflow 上有一个相关问题,如何移动相对符号链接?。另外,在 Unix 和 Linux 上,查找目录树中指向该树外部的所有符号链接,并且(指的是一个更难的问题)是否有某种符号链接支持移动或重命名目标文件?

例如,一个名为mv-relwhich 的命令的行为如下(其他命令是其 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

相关内容