切换符号链接和目录

切换符号链接和目录

我有一个目录和一个符号链接:

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 个对象,例如目录和符号链接。虽然这不会启用原子切换,但它确实允许保留名称dirdir_symlink指向目录的序列。

  1. 创建一个tmp指向 的符号链接tmp
  2. 交换tmpdir.
  3. 替换dir_symlink为指向 的符号链接tmp
  4. 替换dir为指向 的符号链接dir_symlink
  5. 交换tmpdir_symlink.
  6. 删除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");
}

相关内容