【问题标题】:Replace a folder with another folder using mv (without deleting target folder first)使用 mv 将一个文件夹替换为另一个文件夹(不先删除目标文件夹)
【发布时间】:2019-07-25 01:44:33
【问题描述】:

我正在尝试用directory 替换现有的folder,但无法使用 mv 完成它 - 我相信有一种方法,但我只是不知道(还)。即使在查阅手册页和搜索网络之后。

如果/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。

【问题讨论】:

  • 可能是:{ rm -rf /path/to/folder; mv /path/to/directory /path/to/folder; }
  • 我知道我可以先像这样mv folder moved && mv directory folder && rm -r moved 将目标移开,但我认为这是不必要的黑客攻击,会让我有一个文件夹不存在的时刻——这是我想要避免的.
  • 没有捷径;目录和文件之间存在根本差异,您不能像这样一步覆盖一个文件夹。不过,一个重要的问题是,如果 /path/to/folder 暂时不存在,为什么这很重要?
  • 假设folderdirectory 在同一个文件系统上,但是您可以简单地使用ln 而不是cp 来最小化I/O。 ln /path/to/directory/* /path/to/folder && rm -rf /path/to/directory.
  • 简而言之,ln <source> <target> 创建一个新目录条目<target>,它引用与<source> 相同的底层文件。两个名字都不是一个“真实”的名字。两者都引用链接计数为 2 的文件。事实上,rm 实际上并没有删除文件;它只是删除文件的 link。文件系统负责收集没有更多链接的垃圾文件。

标签: bash shell command-line mv


【解决方案1】:

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

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. Also, therm -rfis not atomic, but assuming no one is interested indirectory, that's not an issue. (Although, as files from/path/to/directoryare unlinked, you *can* see changes to the link counts of files under/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 只是同一事物的两个不同名称。所有者前面的数字是链接计数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 会给您一个错误。)

【讨论】:

    猜你喜欢
    • 2012-11-20
    • 2014-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多