shell 使用mv将一个文件夹替换为另一个文件夹(不先删除目标文件夹)

cnjp1d6j  于 2022-12-13  发布在  Shell
关注(0)|答案(1)|浏览(223)

我试图用directory来替换现有的folder,但是用mv做不到a-我相信有一种方法,只是我还不知道。
如果/path/to/仅包含directory,则以下命令会将/path/to/directory(消失)移动到/path/to/folder

mv /path/to/directory /path/to/folder

它基本上是一个重命名,这是我试图实现的。
但是,如果/path/to/folder已经存在,则相同的命令会将/path/to/directory移动到/path/to/folder/directory
我不想使用cp命令来避免IO。

cbjzeqam

cbjzeqam1#

不要使用cp来实际复制每个文件中的 * 数据 *,而是使用ln来“复制”指向文件的 * 指针 *。

ln /path/to/directory/* /path/to/folder && rm -rf /path/to/directory

请注意,这比使用cp * 稍微 * 原子化一些;每个单独的文件在一个步骤中出现在/path/to/folder中(即,/path/to/folder/foo.txt不可能被部分复制),但是仍然存在一个小窗口,其中来自/path/to/directory的一些但不是全部文件已经被链接到folder。而且,rm -rf不是原子的,但是假设没有人对directory感兴趣,这不是问题。(不过,由于来自/path/to/directory的文件被取消链接,您 * 可以 * 看到/path/to/foldoer下的文件的链接计数从2变为1。不太可能有人会关心这个问题。)
你所认为的一个文件实际上只是一个文件系统条目,它指向一个由文件系统管理的匿名文件。

$ mkdir d
$ cd d
$ echo hello > file.txt
$ cp file.txt file_copy.txt
$ ln file.txt file_link.txt
$ ls -li
total 24
12890456377 -rw-r--r--  2 chepner  staff  6 Mar  3 12:46 file.txt
12890456378 -rw-r--r--  1 chepner  staff  6 Mar  3 12:47 file_copy.txt
12890456377 -rw-r--r--  2 chepner  staff  6 Mar  3 12:46 file_link.txt

-i选项将每个条目的inode编号(第一列)添加到输出中; inode可以看作是文件的唯一标识符。在此输出中,可以看到file_copy.txt是一个全新的文件,其inode与file.txt不同。file_link.txt具有完全相同的inode,这意味着file.txtfile_link.txt只是同一个文件的两个不同名称。所有者前面的数字是 link count; file.txtfile_link.txt都引用链接计数为2的文件。
当你使用rm时,你只是删除了一个到文件的 * 链接 *,而不是文件本身。一个文件直到链接计数减少到0时才被删除。为了演示,我们将删除file.txtfile_copy.txt

$ rm file.txt file_copy.txt
$ ls -li
total 8
12890456377 -rw-r--r--  1 chepner  staff  6 Mar  3 12:46 file_link.txt

正如您所看到的,到file_copy的唯一链接消失了,因此inode 12890456378不再出现在输出中。(数据是否 * 真的 * 消失是文件系统实现的问题。)但是,file_link.txt仍然引用与以前相同的文件,但现在链接计数为1,因为file.txt被删除了。
指向文件的链接不必出现在同一目录中;它们可以出现在同一 * 文件系统 * 的任何目录中,这是使用此技巧时需要注意的唯一问题。如果您尝试创建指向另一个文件系统上的文件的链接,ln将(IIRC)给予您一个错误。

相关问题