在 Linux 上不用 mv 命令移动文件

有时候,当您需要移动文件时,mv 命令不是最佳选择。那么,您还有哪些其他方法可以做到这一点呢?
128 位读者喜欢这篇文章。
Why the operating system matters even more in 2017

Internet Archive Book Images。由 Opensource.com 修改。CC BY-SA 4.0

不起眼的 mv 命令是您在遇到的每个 POSIX 系统上都能找到的实用工具之一。它的工作明确定义,并且做得很好:将文件从文件系统中的一个位置移动到另一个位置。但是,如果 Linux 不是灵活的,那它就什么都不是了,并且还有其他移动文件的选项。使用不同的工具可以提供小的优势,这些优势非常适合特定的用例。

在远离 mv 之前,先看看此命令的默认结果。首先,创建一个目录并生成一些权限设置为 777 的文件

$ mkdir example
$ touch example/{foo,bar,baz}
$ for i in example/*; do ls /bin > "${i}"; done 
$ chmod 777 example/*

您可能不会这样想,但是文件以条目的形式存在,称为索引节点(通常称为 inodes),位于文件系统中。您可以使用 ls 命令及其 --inode 选项查看文件占用的 inode

$ ls --inode example/foo
7476868 example/foo

作为测试,将该文件从示例目录移动到当前目录,然后查看文件的属性

$ mv example/foo .
$ ls -l -G -g --inode
7476868 -rwxrwxrwx. 1 29545 Aug  2 07:28 foo

如您所见,原始文件及其现有权限已被“移动”,但其 inode 没有更改。

这就是 mv 工具被编程为移动文件的方式:保持 inode 不变(除非文件被移动到不同的文件系统),并保留其所有权和权限。

其他工具提供了不同的选项。

复制和删除

在某些系统上,移动操作是真正的移动操作:位从文件系统中的一个点移除并重新分配到另一个点。这种行为在很大程度上已经不受欢迎了。移动操作现在要么是属性重新分配(inode 现在指向文件组织中的不同位置),要么是复制操作后跟删除操作的合并。

这种设计的哲学意图是确保,如果移动失败,文件不会留下碎片。

mv 不同,cp 命令在您的文件系统中创建一个全新的数据对象。它具有新的 inode 位置,并且受您的活动 umask 的约束。您可以使用 cprm(或者如果您安装了 trash)命令来模拟移动

$ cp example/foo .
$ ls -l -G -g --inode
7476869 -rwxrwxr-x. 29545 Aug  2 11:58 foo
$ trash example/foo

本例中新的 foo 文件获得了 775 权限,因为该位置的 umask 特别排除了写入权限

$ umask
0002

有关 umask 的更多信息,请阅读 Alex Juarez 关于文件权限的文章。

Cat 和删除

与复制和删除类似,使用 cat(或 tac,就此而言)命令在创建“移动”文件时分配不同的权限。假设一个新的测试环境,当前目录中没有 foo

$ cat example/foo > foo
$ ls -l -G -g --inode
7476869 -rw-rw-r--. 29545 Aug 8 12:21 foo
$ trash example/foo

这次,创建了一个没有预先设置权限的新文件。结果完全取决于 umask 设置,该设置不阻止用户和组的任何权限位(无论 umask 如何,都不会授予新文件的可执行位),但它阻止了其他人的写入(值 2)位。结果是一个权限为 664 的文件。

Rsync

rsync 命令是一个强大的多用途工具,用于在主机和文件系统位置之间发送文件。此命令有许多可用选项,包括使其目标镜像其源的功能。

您可以使用 rsync 命令的 --remove-source-files 选项以及您选择执行同步的任何其他选项(常见的通用选项是 --archive)复制然后删除文件

$ rsync --archive --remove-source-files example/foo .
$ ls example
bar  baz
$ ls -lGgi
7476870 -rwxrwxrwx. 1 seth users 29545 Aug 8 12:23 foo

在这里您可以看到文件权限和所有权被保留,时间戳已更新,并且源文件已被删除。

警告: 不要将此选项与 --delete 混淆,后者从您的目标目录中删除文件。误用 --delete 可能会擦除您的大部分数据,建议您避免使用此选项,除非在测试环境中。

您可以覆盖其中一些默认设置,更改权限和修改设置

$ rsync --chmod=666 --times \
--remove-source-files example/foo .
$ ls example
bar  baz
$ ls -lGgi
7476871 -rw-rw-r--. 1 seth users 29545 Aug 8 12:55 foo

在这里,目标位置的 umask 受到尊重,因此 --chmod=666 选项导致文件具有 664 权限。

好处不仅仅在于权限。rsync 命令有 许多 有用的 选项(其中最不重要的是 --exclude 标志,因此您可以从大型移动操作中排除项目),这使其成为比简单的 mv 命令更强大的工具。例如,要在移动文件集合时排除所有备份文件

$ rsync --chmod=666 --times \
--exclude '*~' \
--remove-source-files example/foo .

使用 install 设置权限

install 命令是一个专门为开发人员设计的复制命令,主要在软件编译的安装例程中调用。它在用户中并不为人所知(我经常想知道为什么它会得到如此直观的名称,而将简单的首字母缩写词和宠物名称留给包管理器),但 install 实际上是将文件放置在您想要的位置的有用方法。

install 命令有很多选项,包括 --backup--compare 命令(以避免“更新”文件的较新副本)。

cpcat 不同,但与 mv 完全一样,install 命令可以在复制文件时保留其时间戳

$ install --preserve-timestamp example/foo .
$ ls -l -G -g --inode
7476869 -rwxr-xr-x. 1 29545 Aug  2 07:28 foo
$ trash example/foo

在这里,文件被复制到一个新的 inode,但其 mtime 没有更改。但是,权限已设置为 install 默认值 755

您可以使用 install 设置文件的权限、所有者和组

$ install --preserve-timestamp \
--owner=skenlon \
--group=dialout \
--mode=666 example/foo .
$ ls -li
7476869 -rw-rw-rw-. 1 skenlon dialout 29545 Aug  2 07:28 foo
$ trash example/foo

移动、复制和删除

文件包含数据,真正重要的文件包含您的数据。学习明智地管理它们很重要,现在您拥有确保以您想要的方式处理数据的工具包。

您是否有管理数据的其他方式?请在评论中告诉我们您的想法。

标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。他曾在电影和计算机行业工作,并且经常同时工作。

5 条评论

对于文件,您还可以从新位置(在同一挂载点内)创建文件的硬链接,然后删除原始文件。

好主意,谢谢!真希望我能想到!

回复 作者 Gautham Ganapathy (未验证)

我不知道“install”。谢谢你的展示,Seth。

回复:“与 cp 和 cat 不同,但与 mv 完全一样,install 命令可以在复制文件时保留其时间戳....”

“cp” 也可以使用“-p”或“-preserve”选项保留 atime 和 mtime。

据我所知,任何修改文件元数据的操作(包括 cp、mv 和 install)都会更新 ctime,并且无法保留 ctime。

我最喜欢的复制整个目录的方法之一是 cpio,例如

cd /old/source/ && find . | cpio -pdmv /new/destination

首先,您可以通过大量的 find 选项完全轻松地控制将找到的内容,其次,cpio 工具几乎在到目前为止我遇到的每个 *NIX 系统上都能找到。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.