在 Linux 中复制文件

了解在 Linux 上复制文件的多种方法以及每种方法的优点。
128 位读者喜欢这个。
Filing papers and documents

过去,复制文档需要办公室的专职人员,然后需要专门的机器。 如今,复制是计算机用户毫不犹豫地执行的任务。 在计算机上复制数据非常简单,以至于在您没有意识到的情况下就进行了复制,例如将文件拖到外部驱动器时。

数字实体易于复制的概念非常普遍,因此大多数现代计算机用户不会考虑复制工作的可用选项。 然而,在 Linux 上复制文件有几种不同的方法。 每种方法都有细微的特性,可能会对您有所帮助,具体取决于您需要完成的工作。

以下是在 Linux、BSD 和 Mac 上复制文件的几种方法。

在 GUI 中复制

与大多数操作系统一样,如果您喜欢这种工作方式,则可以在 GUI 中完成所有文件管理。

拖放

复制文件最明显的方法是您可能习惯于在计算机上复制文件的方式:拖放。 在大多数 Linux 桌面环境中,默认情况下,将文件从一个本地文件夹拖放到另一个本地文件夹会移动文件。 您可以在开始拖动文件后按住 Ctrl 键,将此行为更改为复制操作。

您的光标可能会显示一个指示符,例如加号,以表明您处于复制模式

Copying a file.

请注意,如果文件存在于远程系统上,无论是 Web 服务器还是您通过文件共享协议访问的自己网络上的另一台计算机,默认操作通常是复制,而不是移动文件。

右键单击

如果您发现拖放文件在您的桌面上不精确或笨拙,或者这样做会使您的手远离键盘太长时间,您通常可以使用右键单击菜单复制文件。 这种可能性取决于您使用的文件管理器,但通常,右键单击会生成一个上下文菜单,其中包含常用操作。

上下文菜单复制操作将文件路径(文件在系统上的位置)存储在您的剪贴板中,以便您可以将文件粘贴到其他地方

Copying a file from the context menu.

在这种情况下,您实际上并没有将文件的内容复制到剪贴板。 相反,您正在复制文件路径。 粘贴时,您的文件管理器会查看剪贴板中的路径,然后运行复制命令,将位于该路径的文件复制到您要粘贴到的路径。

在命令行上复制

虽然 GUI 是一种通常熟悉的复制文件的方式,但在终端中复制可能更有效。

cp

在桌面环境中复制和粘贴文件的显而易见的终端等效项是 cp 命令。 此命令复制文件和目录,并且相对简单。 它使用熟悉的目标(严格按照该顺序)语法,因此要将名为 example.txt 的文件复制到您的 Documents 目录中

$ cp example.txt ~/Documents

就像将文件拖放到文件夹上时一样,此操作不会用 example.txt 替换 Documents。 相反,cp 会检测到 Documents 是一个文件夹,并将 example.txt 的副本放入其中。

您还可以方便(且高效)地在复制文件时重命名该文件

$ cp example.txt ~/Documents/example_copy.txt

这个事实很重要,因为它允许您在与原始文件相同的目录中创建文件的副本

$ cp example.txt example.txt
cp: 'example.txt' and 'example.txt' are the same file.
$ cp example.txt example_copy.txt

要复制目录,您必须使用 -r 选项,该选项代表 --recursive。 此选项在目录 inode 上运行 cp,然后在目录中的所有文件上运行。 如果没有 -r 选项,cp 甚至无法识别目录是可以复制的对象

$ cp notes/ notes-backup
cp: -r not specified; omitting directory 'notes/'
$ cp -r notes/ notes-backup

cat

cat 命令是最容易被误解的命令之一,但这只是因为它体现了 POSIX 系统的极端灵活性。 在 cat 所做的所有其他事情(包括其连接文件的预期目的)中,它也可以复制。 例如,使用 cat,您只需一个命令即可从一个文件创建两个副本。 您无法使用 cp 执行此操作。

使用 cat 复制文件的意义在于系统解释该操作的方式。 当您使用 cp 复制文件时,文件的属性会与文件本身一起复制。 这意味着副本的文件权限与原始文件相同

$ ls -l -G -g
-rw-r--r--. 1 57368 Jul 25 23:57  foo.jpg
$ cp foo.jpg bar.jpg
-rw-r--r--. 1 57368 Jul 29 13:37  bar.jpg
-rw-r--r--. 1 57368 Jul 25 23:57  foo.jpg

但是,使用 cat 将文件的内容读取到另一个文件,会调用一个系统调用来创建一个新文件。 这些新文件受您的默认 umask 设置的约束。 要了解有关 umask 的更多信息,请阅读 Alex Juarez 的文章,该文章涵盖了 umask 以及一般权限。

运行 umask 以获取当前设置

$ umask
0002

此设置意味着在此位置创建的新文件将被授予 664 (rw-rw-r--) 权限,因为 umask 设置的前几位没有任何屏蔽(并且可执行位不是文件创建的默认位),并且写入权限被最后一位阻止。

当您使用 cat 复制时,您实际上并没有复制文件。 您使用 cat 读取文件的内容,然后将输出重定向到新文件中

$ cat foo.jpg > baz.jpg
$ ls -l -G -g
-rw-r--r--. 1 57368 Jul 29 13:37  bar.jpg
-rw-rw-r--. 1 57368 Jul 29 13:42  baz.jpg
-rw-r--r--. 1 57368 Jul 25 23:57  foo.jpg

如您所见,cat 使用系统的默认 umask 创建了一个全新的文件。

最后,当您只想复制文件时,技术细节通常并不重要。 但有时您想复制文件并最终获得一组默认权限,使用 cat,您可以在一个命令中完成所有操作

rsync

rsync 命令是复制文件的通用工具,具有同步源和目标的显着能力。 在最简单的情况下,rsync 可以以类似于 cp 命令的方式使用

$ rsync example.txt example_copy.txt
$ ls 
example.txt    example_copy.txt

该命令的真正威力在于它能够在不必要时复制。 如果您使用 rsync 将文件复制到目录中,但该文件已经存在于该目录中,则 rsync 不会费心执行复制操作。 在本地,这一事实并不一定意味着什么,但如果您要将千兆字节的数据复制到远程服务器,此功能会产生很大的不同。

但是,即使在本地,真正起作用的是该命令能够区分共享相同名称但包含不同数据的文件。 如果您曾经面临过两个意图相同的目录副本,则 rsync 可以将它们同步到一个目录中,该目录包含每个目录的最新更改。 这种设置在尚未发现版本控制魔力的行业中以及在传播一个真理来源的备份解决方案中非常常见。

您可以通过创建两个文件夹来有意识地模拟这种情况,一个名为 example,另一个名为 example_dupe

$ mkdir example example_dupe

在第一个文件夹中创建一个文件

$ echo "one" > example/foo.txt

使用 rsync 同步两个目录。 此操作最常见的选项是 -a(对于 archive,这确保了保留符号链接和其他特殊文件)和 -v(对于 verbose,向您提供有关命令进度的反馈)

$ rsync -av example/ example_dupe/

这些目录现在包含相同的信息

$ cat example/foo.txt
one
$ cat example_dupe/foo.txt
one

如果您要视为源的文件发散了,则目标会更新以匹配

$ echo "two" >> example/foo.txt
$ rsync -av example/  example_dupe/
$ cat example_dupe/foo.txt
one
two

请记住,rsync 命令旨在复制数据,而不是充当版本控制系统。 例如,如果目标中的文件以某种方式领先于源文件,则该文件仍然会被覆盖,因为 rsync 会比较文件的发散情况,并假定目标始终旨在镜像源

$ echo "You will never see this note again" > example_dupe/foo.txt
$ rsync -av example/  example_dupe/
$ cat example_dupe/foo.txt
one
two

如果没有更改,则不会发生复制。

rsync 命令具有许多 cp 中没有的选项,例如设置目标权限、排除文件、删除未出现在两个目录中的过期文件等等。 使用 rsync 作为 cp 的强大替代品,或者仅用作有用的补充。

多种复制方式

在 POSIX 系统上有很多方法可以实现基本相同的结果,因此开源在灵活性方面的声誉似乎当之无愧。 我是否遗漏了一种有用的复制数据的方式? 在评论中分享您的复制技巧。

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

4 条评论

感谢您对复制机制的深入研究,Seth。 很容易忘记复制文件不仅仅是使用图形文件管理器或 cp。 或者您可以使用 rsync 在计算机上的一个文件夹和另一个文件夹之间复制文件 — 我只使用它在计算机之间复制。

当我将 /home/gregp 目录备份到外部驱动器时,我首先转到上一层,然后
cp -av gregp /destination
-a 标志代表 archive,与 -dR 相同,一个重要的特性是它保留时间戳。 有时我发现自己会根据创建或上次保存文件的时间来查找文件,因此时间戳非常有用。 我为什么要转到上一层而不是仅仅停留在 /home/gregp 中并执行此操作?
cp -av * /destination
原因是此方法不会复制点文件和点目录(所谓的隐藏文件)。
一个(某种程度上)与 cp 相关的命令是 mv,因为它在某种意义上是复制文件,然后删除原始文件。据我所知,它是通过更改文件注册表来实现的,而不是实际复制,因为 mv 保留了与原始文件相同的时间戳。

mv 可以在其目录条目中重命名文件,或者将名称放在其他目录中,或者重命名并将名称放在其他目录中。 在任何一种情况下,文件的 inode 号码在移动后都不会改变,因此不会触及文件的数据块。

但是,如果目标位于不同的文件系统上,mv 会将数据块复制到新位置,然后从原始目录中删除目录条目(名称:inode 对)。

当文件被移动 (mv) 时,修改时间 (mtime) 保持不变,因为文件数据没有改变(尽管它可能已被复制到不同的文件系统)。

在任何一种情况下,您都应该看到更新后的 ctime(更改时间),因为文件元数据(名称)已更改。

回复 ,作者:Greg P

非常完整的指南。也许可以提及在 cp 命令中使用通配符(如 *)的强大功能,例如。 简单易用且非常强大 ;-)

© . All rights reserved.