我有一个目录和一个符号链接:
mkdir dir
ln -s dir dir_symlink
我想用目录替换符号链接,用符号链接替换目录。有没有办法以原子方式(或非常快)做到这一点?目录很大。
dir
现在应该是目录的符号链接dir_symlink
(不再是符号链接,并且包含 的以前的内容dir
)。
答案1
如果我必须经常这样做,我会编写一个像这样的小 bash 脚本:
#!/bin/bash
echo "select symlink"
read -e -r symlink
echo "select directory"
read -e -r dir
var=$(echo "$dir" | sed 's/\///g')
rm "$symlink"
mv "$dir" "$symlink"
ln -s "$symlink" "$var"
该sed
命令会删除/
当您使用自动完成输入时添加的 。
笔记:如果您选择了目录树,它也会删除所有这些内容。
您可以告诉sed
只匹配行尾,如下所示:
sed 's/\/*$//g'
答案2
如果目录位于同一文件系统上,mv
则仅重命名目录,不涉及任何复制。只需删除旧的符号链接,使用重命名目录mv
并创建一个新的符号链接。
答案3
值得注意的是,如果这是在 macOS 计算机上,新的 APFS 文件系统仅支持此类场景的原子交换。虽然该功能似乎没有内置到 mv 这样的命令中,但可以通过一点 Swift 代码来访问它(C 代码几乎相同,但您可以轻松地将其粘贴到 Swift REPL 中,这更容易):
import Foundation
renamex_np("/path/to/file/one", "/path/to/file/two", UInt32(RENAME_SWAP))
答案4
从 Linux 3.15(和 glibc 2.28)开始,renameat2
带有该选项的系统调用RENAME_EXCHANGE
将自动交换 2 个对象,例如目录和符号链接。虽然这不会启用原子切换,但它确实允许保留名称dir
并dir_symlink
指向目录的序列。
- 创建一个
tmp
指向 的符号链接tmp
。 - 交换
tmp
和dir
. - 替换
dir_symlink
为指向 的符号链接tmp
。 - 替换
dir
为指向 的符号链接dir_symlink
。 - 交换
tmp
和dir_symlink
. - 删除
tmp
。
在C中:
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main() {
symlink("tmp", "tmp");
renameat2(AT_FDCWD, "tmp", AT_FDCWD, "dir", RENAME_EXCHANGE);
symlink("tmp", "tmp_link");
rename("tmp_link", "dir_symlink");
symlink("dir_symlink", "tmp_link");
rename("tmp_link", "dir");
renameat2(AT_FDCWD, "tmp", AT_FDCWD, "dir_symlink", RENAME_EXCHANGE);
unlink("tmp");
}