シンボリックリンクとディレクトリ切り替え

シンボリックリンクとディレクトリ切り替え

ディレクトリとシンボリックリンクがあります。

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. 交換しtmpてくださいdir
  3. dir_symlinkを指すシンボリックリンクに置き換えられましたtmp
  4. dirを指すシンボリックリンクに置き換えられましたdir_symlink
  5. 交換しtmpてくださいdir_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");
}

関連情報