cpの代わりに一時ファイルにファイルを交換しますか? [コピー]

cpの代わりに一時ファイルにファイルを交換しますか? [コピー]

両方の変数を交換する必要がある有名な入門プログラミングの練習があります。確実な解決策は、3番目の一時変数を使用することです。しかし、言語にタプルのようなものがあれば、引数を逆の順序で返す非常に単純なヘルパー関数を書くことができます。

def swap(a: Int, b: Int): (Int, Int) = (b, a)
val (two, one) = swap(1, 2) // => (2, 1)

Linuxでのファイル操作でもこれが可能かどうか疑問に思います。たとえば、状況に応じて変更したい設定がある場合は、2つのファイル名を取得してその内容を変更するコマンドがありますか?
たとえば、a.txt ファイルの内容が「Hello」で、b.txt の内容が「World」であるとします。ここで呼び出したものを呼び出した後、swapa.txtに「World」を、b.txtに「Hello」を含めたいと思います。

この問題は、スワップパーティションがすべての検索結果を支配していたため、最初に考えたよりも調査するのが困難でした。

答え1

カーネルレベルでこれを行うLinux固有のシステムコールがあります。

関連するシステムコールは次のとおりです。renameat2()renameat()これは、この問題を解決するために追加の特定のフラグで使用できるLinux固有の拡張です。 Linux 3.15 に追加され、glibc サポートが glibc 2.28 に追加されました。

RENAME_EXCHANGE

原子交換古い道そして新しい道。両方のパス名が存在する必要がありますが、タイプが異なる場合があります。たとえば、1つは空でないディレクトリ、もう1つはシンボリックリンクです。

この機能をサポートできるファイルシステムには追加の制限があります。これ子検索2014年以降に追加されたさまざまなファイルシステムのサポートの紹介:ext4、ヒューズ、f2fs、shmem / tmpfs、xfs、gfs2、overlayfs、btrfs、ubifs、affs ...

このシステムコールを使用するための正しいコマンドがない場合、以下はすべてのシンボルが「手動で」(このアーキテクチャ= 316など)原子的に解決される非常にアーキテクチャ固有(amd64 / x86_64)Pythonの例です。SYS_renameat2Cでシステムコールが実行するアクションを示すと名前のスワップファイル:abstrace

$ echo Hello > a.txt; echo World > b.txt
$ cat a.txt
Hello
$ cat b.txt
World
$ strace -e trace=renameat2 python3 -c 'import ctypes; libc = ctypes.CDLL(None); libc.syscall(316, -100, b"a.txt", -100, b"b.txt", 2);'
renameat2(AT_FDCWD, "a.txt", AT_FDCWD, "b.txt", RENAME_EXCHANGE) = 0
+++ exited with 0 +++
$ cat a.txt
World
$ cat b.txt
Hello

もちろん適切な図書館会議単純化するこのPythonの例。

答え2

そんなことはないようです。基準システムコール。しかし、Linuxには1つあります。

専用のシステムコールがあるかどうかは重要です。rename(a, tmp); rename(b, a); rename(tmp, b);これはすべてのシステムでこれを行うことができますが、アトミックではないためです。同時に実行中の他のプロセスでa名前を変更した後にそのプロセスを開こうとすると、「ファイルが見つかりません」というエラーが表示されることがあります。最初に交換してもrename()常にlink()存在することを確認してください。別のプロセスで同じファイルを開いてインポートできますaab

幸いなことに、2つのファイルを交換する必要があることはあまりありません(2つの変数を交換することが一般的な要件であるかどうかはわかりません)。代わりに、リーダーが部分的、混在、または失われたデータを取得できる場所を残すことなく、単一のファイル名に続くものを変更する方が一般的です。これはrename()またはをlink()介して簡単に実行できますsymlink()

ある構成セットから別の構成セットに変更する例の場合は、アクティブ構成のシンボリックリンクを作成してから自動的にリンクを置き換えることができます。

たとえば、次のような場合

$ ls -l
total 8
-rw-r--r-- 1 ilkkachu ilkkachu  6 Oct 17 21:07 conf1
-rw-r--r-- 1 ilkkachu ilkkachu 13 Oct 17 21:07 conf2
lrwxrwxrwx 1 ilkkachu ilkkachu  5 Oct 17 21:07 current -> conf1

これにより、ln -sf conf2 current自動的に次のように変更されます。

$ ls -l
total 8
-rw-r--r-- 1 ilkkachu ilkkachu  6 Oct 17 21:07 conf1
-rw-r--r-- 1 ilkkachu ilkkachu 13 Oct 17 21:07 conf2
lrwxrwxrwx 1 ilkkachu ilkkachu  5 Oct 17 21:07 current -> conf2

conf1同様に、同じファイルへのハードリンクとして使用し、リンクをにcurrent置き換えることができますln -f conf2 current

答え3

避けたいと思います。ファイル内容のコピーファイルを使用してこれを達成する2つの方法を考えることができます。

  1. mvコンテンツをコピーせずに一時ファイルを介してファイル名を変更するために使用されます。

  2. ポインタに似たシンボリックリンクを使用して置き換える代わりに、必要な設定を明示的に設定します。例えば

    
    $ls
    a.txt b.txt Define_setcfg.bash
    $cata.txt
    こんにちは
    $catb.txt
    世界
    $cat 定義_setcfg.bash
    関数 setcfg() {
    echo Set設定を$ 1#$ 1が有効なcfgファイル名に設定されていることを確認する必要があります。
    ln -sf $1actual.cfg # Actual.cfg という名前の $1 シンボリックリンクを生成します。
    }   
    
    $source ./define_setcfg.bash # 現在の bash での関数の定義
    $setcfg b.txt#setcfg 関数の使用
    設定をb.txtに設定
    $ ls -l # 今持っているものを確認
    合計12個
    lrwxrwxrwx 1ユーザー名ユーザー名5 10月17日18:33 Actual.cfg - > b.txt
    -rw-rw-r-- 1ユーザー名ユーザー名6 10月17日18:08 a.txt
    -rw-rw-r-- 1ユーザー名ユーザー名6 10月17日18:08 b.txt
    -rw-rw-r-- 1ユーザー名ユーザー名161 10月17日18:25 Define_setcfg.bash
    $ setcfg a.txt#パラメータ1としてa.txtを提供する関数を使用します。
    設定をa.txtに設定
    $ ls -l # 今持っているものを確認
    合計12個
    lrwxrwxrwx 1ユーザー名ユーザー名5 10月17日18:34 Actual.cfg - > a.txt
    -rw-rw-r-- 1ユーザー名ユーザー名6 10月17日18:08 a.txt
    -rw-rw-r-- 1ユーザー名ユーザー名6 10月17日18:08 b.txt
    -rw-rw-r-- 1ユーザー名ユーザー名161 10月17日18:25 Define_setcfg.bash
    $   

答え4

これらのコマンドは簡単に作成できるため、数字が存在するかどうか疑問に思います。しかし、なぜ?

あなたが本当に解決しなければならない問題は何ですか?ほとんどの場合、より良い方法があります。

特定の名前のファイルを読み取るプログラムがあり、2つのバージョンが必要な場合、一般的に私がすることは、ファイルシステムに可用性を表す2つのバージョンを置き、名前のあるシンボリックリンクを使用してそれらの1つを指すことです。 。プログラム名です。実際の使用。次に、(を使用して)シンボリックリンクを更新してln -sf2つの間を変更します。

関連情報