有一个著名的入门级编程练习,要求您交换两个变量。显而易见的解决方案是使用第三个临时变量。但是,如果您的语言有类似元组的东西,您可以编写一个非常简单的辅助函数,以相反的顺序返回其参数:
def swap(a: Int, b: Int): (Int, Int) = (b, a)
val (two, one) = swap(1, 2) // => (2, 1)
Run Code Online (Sandbox Code Playgroud)
我想知道Linux上的文件操作是否也可以这样。例如,如果我有一个要根据情况交换的配置,是否有一个命令可以获取两个文件名并交换它们的内容?
例如,假设文件 a.txt 的内容为“Hello”,而 b.txt 的内容为“World”。调用我在这里调用的内容后swap
,我希望 a.txt 包含“World”和 b.txt“Hello”。
这个问题比我最初想象的更难研究,因为交换分区主导了所有搜索结果。
A.B*_*A.B 13
有一个特定于 Linux 的系统调用能够在内核级别执行此操作。
相关的系统调用是renameat2()
Linux 特定的扩展renameat()
,可以与附加的特定标志一起使用来解决这个问题。Linux 3.15 中添加了它,glibc 2.28 中添加了 glibc 支持。
原子交换oldpath和newpath。两个路径名都必须存在,但可以是不同的类型(例如,一个可以是非空目录,另一个可以是符号链接)。
哪些文件系统可以支持此功能可能还有进一步的限制。这个git 搜索讲述了自 2014 年以来添加的各种文件系统的支持:ext4、fuse、f2fs、shmem/tmpfs、xfs、gfs2、overlayfs、btrfs、ubifs、affs ...
如果没有正确的命令来使用此系统调用,这里有一个 Python 中的示例,该示例非常特定于体系结构 (amd64/x86_64),其中所有符号均“手动”解析(在此体系结构中为= 316 等),以原子方式交换名为和的SYS_renameat2
文件,显示 C 中的系统调用会执行什么操作:a
b
strace
$ 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
Run Code Online (Sandbox Code Playgroud)
我不认为有这样一个标准的系统调用。不过 Linux 上有一个。
拥有或不拥有专用系统调用很重要,因为虽然您当然可以rename(a, tmp); rename(b, a); rename(tmp, b);
在任何系统上执行此操作,但它不是原子的。同时运行的另一个进程可能会a
在重命名后立即尝试打开,并且会收到“文件未找到”错误。即使您首先将其替换rename()
为link()
,确保它a
始终存在,另一个进程也可能能够打开a
和b
并获取相同的文件。
幸运的是,并不经常需要交换两个文件(我也不确定交换两个变量是否是常见的需要)。相反,更常见的需求是替换单个文件名后面的内容,而不留下读者可能获得部分、混合或丢失数据的点。这可以通过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
Run Code Online (Sandbox Code Playgroud)
然后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
Run Code Online (Sandbox Code Playgroud)
同样,您可以将conf1
和current
作为指向同一文件的硬链接,并将链接替换为ln -f conf2 current
.
归档时间: |
|
查看次数: |
908 次 |
最近记录: |