cp 命令的两个妙用

Linux 的复制命令可以快速完成专门备份。
440 位读者喜欢这篇文章。
How Linux got to be Linux: Test driving 1993-2003 distros

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

Linux 上提供的点按式图形用户界面非常棒……但如果您最喜欢的交互式开发环境由终端窗口、Bash、Vim 和您最喜欢的语言编译器组成,那么就像我一样,您会经常使用终端。

但即使是通常避免使用终端的人也可以通过更多地了解其环境提供的丰富功能而受益。 其中一个例子是 cp 命令。 根据维基百科cp(或复制)命令是 Unix 的版本 1 的一部分。 除了其他一些精选命令——我想到了 lsmvcdpwdmkdirvishsedawk——cp 是我在 1984 年使用 System V Unix 的最初几个步骤之一。 cp 最常见的用途是复制文件,例如

cp sourcefile destfile

在终端会话中发出命令提示符。 上述命令将名为 sourcefile 的文件复制到名为 destfile 的文件。 如果在发出命令之前 destfile 不存在,则会创建它; 如果它确实存在,则会被覆盖。

我不知道我使用过这个命令多少次(也许我不想知道),但我确实知道,当我在编写和测试代码,并且有一个我希望保持原样的工作版本时,我经常使用它,然后再继续。 所以,在过去的 30 多年里,我可能已经在命令提示符下输入过类似这样的内容

cp test1.py test1.bak

至少一万亿次。 或者,我可能决定继续使用我的测试程序的版本 2,在这种情况下,我可能已经输入

cp test1.py test2.py

以完成该移动的第一步。

这是一件非常常见和简单的事情,所以我很少查看 cp 的参考文档。 但是,在备份我的“图片”文件夹(使用 GUI 环境中的“文件”应用程序)时,我开始思考,“我想知道是否有选项让 cp 仅复制新文件或已更改的文件?” 果然,有!

妙用 #1:更新文件夹的第二个副本

假设我的电脑上有一个文件夹,其中包含一组文件。 此外,假设我时不时地将一个新文件放入该集合中。 最后,假设我时不时地以某种方式编辑这些文件中的一个。 这样的集合的一个例子可能是我从手机下载的照片或我的音乐文件。

假设这个文件集合对我来说有一些持久的价值,我可能会偶尔想制作它的副本——一种“快照”——将其保存在其他媒体上。 当然,有许多实用程序可用于进行备份,但也许我希望在通常离线存储甚至连接到另一台计算机的可移动设备上复制此确切结构。

cp 命令提供了一种非常简单的方法来做到这一点。 这是一个例子。

在我的 Pictures 文件夹中,我有一个名为 Misc 的子文件夹。 为了说明的目的,我将在 USB 记忆棒上复制它。 我们开始吧!

me@desktop:~/Pictures$ cp -r Misc /media/clh/4388-D5FE
me@desktop:~/Pictures$

以上几行是从我的终端窗口按原样复制的。 对于那些可能不太熟悉该环境的人来说,值得注意的是 me @mydesktop:~/Pictures$ 是终端在每次输入和执行命令之前提供的命令提示符。 它标识用户 (me)、计算机 (mydesktop) 和当前工作目录,在本例中为 ~/Pictures,它是 /home/me/Pictures 的简写,即我的主目录中的 Pictures 文件夹。

我输入并执行的命令 cp -r Misc /media/clh/4388-D5FE 将文件夹 Misc 及其所有内容(-r 或“递归”选项指示内容以及文件夹或文件本身)复制到文件夹 /media/clh/4388-D5FE 中,我的 USB 驱动器就安装在该文件夹中。

执行该命令后,我返回到原始提示符。 与从 Unix 继承的大多数命令一样,如果命令执行时没有检测到任何异常结果,它将不会在终止前打印出“执行成功”之类的消息。 想要更多反馈的人可以使用 -v 选项来使执行“verbose”。

下面是我在 USB 驱动器上 Misc 的新副本的图像。 该目录中有九个 JPEG 文件。

Image of the new copy of Misc on the USB drive

opensource.com

假设我向目录 ~/Pictures/Misc 的主副本添加了一些新文件,现在它看起来像这样

New files added to the master directory

opensource.com

现在我只想将新文件复制到我的记忆棒上。 为此,我将使用 cp 的“更新”和“verbose”选项

me@desktop:~/Pictures$ cp -r -u -v Misc /media/clh/4388-D5FE
'Misc/asunder.png' -> '/media/clh/4388-D5FE/Misc/asunder.png'
'Misc/editing tags guayadeque.png' -> '/media/clh/4388-D5FE/Misc/editing tags guayadeque.png'
'Misc/misc on usb.png' -> '/media/clh/4388-D5FE/Misc/misc on usb.png'
me@desktop:~/Pictures$

上面的第一行显示了 cp 命令及其选项(-r 代表“递归”,-u 代表“更新”,-v 代表“verbose”)。 接下来的三行显示了被复制的文件。 最后一行再次显示命令提示符。

一般来说,诸如 -r 之类的选项也可以以更详细的方式给出,例如 --recursive。 简短形式,它们也可以组合在一起,例如 -ruv

妙用 #2 – 制作版本备份

回到我最初的例子,即对开发中的代码的工作版本进行定期备份,我从学习更新中发现的另一个非常有用的 cp 选项是 backup。

假设我打算编写一个非常有用的 Python 程序。 作为迭代开发的爱好者,我可能会先让一个简单的程序版本工作,然后逐步向其中添加更多功能,直到它完成工作。 假设我的第一个版本只是使用 Python print 命令打印字符串“hello world”。 这是一个单行程序,如下所示

print 'hello world'

我已将该字符串放入文件 test1.py 中。 我可以从命令行运行它,如下所示

me@desktop:~/Test$ python test1.py
hello world
me@desktop:~/Test$

现在程序正在运行,我想在添加下一个组件之前对其进行备份。 我决定使用带有编号的备份选项,如下所示

clh@vancouver:~/Test$ cp --force --backup=numbered test1.py test1.py
clh@vancouver:~/Test$ ls
test1.py  test1.py.~1~
clh@vancouver:~/Test$ 

那么,这一切意味着什么?

首先,--backup=numbered 选项表示,“我想进行备份,并且我希望连续备份进行编号。” 所以第一个备份将是数字 1,第二个是数字 2,依此类推。

其次,请注意源文件和目标文件相同。 通常,如果我们尝试使用 cp 命令将文件复制到自身上,我们将收到一条消息,例如

cp: 'test1.py' and 'test1.py' are the same file

在我们要进行备份并且我们想要相同的源和目标这种特殊情况下,我们使用 --force 选项。

第三,我使用 ls(或“list”)命令来显示我们现在有一个名为 test1.py 的文件,它是原始文件,还有一个名为 test1.py.~1~ 的文件,它是备份文件。

假设现在我想添加到程序的第二个功能是另一个 print 语句,它打印字符串“Kilroy was here”。 现在文件 test1.py 中的程序如下所示

print 'hello world'
print 'Kilroy was here'

看看 Python 编程是多么简单? 无论如何,如果我再次执行备份步骤,这就是发生的事情

clh@vancouver:~/Test$ cp --force --backup=numbered test1.py test1.py
clh@vancouver:~/Test$ ls
test1.py test1.py.~1~ test1.py.~2~
clh@vancouver:~/Test$

现在我们有两个备份文件:test1.py.~1~,其中包含原始的单行程序,以及 test1.py.~2~,其中包含两行程序,我可以继续添加和测试更多功能。

这对我来说太有用了,我正在考虑创建一个 shell 函数来简化它。

总结三点

首先,Linux 手册页默认安装在大多数桌面和服务器发行版上,提供了命令(如 cp)的详细信息和偶尔有用的示例。 在终端中,输入命令

man cp

对于只想学习如何首先使用命令的用户来说,这些解释可能既密集又晦涩。 对于那些倾向于坚持不懈的人,我建议创建一个测试目录和文件,并在那里尝试该命令和选项。

其次,如果对教程更感兴趣,那么在您喜欢的搜索引擎中键入搜索字符串“linux shell tutorial”会调出许多有趣且有用的资源。

第三,如果您想知道,“当 GUI 通常通过点按式方式提供相同的功能时,为什么要费心呢?” 我有两个回应。 首先是“点按式”并不总是那么容易,尤其是在它扰乱了另一个工作流程并且需要大量的点和大量的点击才能使其工作时。 第二是重复性任务通常可以通过使用 shell 脚本、shell 函数和 shell 别名来轻松简化。

您是否以新的或有趣的方式使用 cp 命令? 请在评论中告诉我们。

标签
Chris Hermansen portrait Temuco Chile
自从 1978 年从不列颠哥伦比亚大学毕业以来,我就很少没有某种计算机。自 2005 年以来,我一直是全职 Linux 用户,从 1986 年到 2005 年,我一直是全职 Solaris 和 SunOS 用户,在此之前,我是 UNIX System V 用户。

13 条评论

感谢 Chris 及时提醒我这些选项的用处。 阅读完这篇文章后不久,它们就派上了用场!

在我升级到新版本的 Fedora 之前,我会将我的主目录 /home/gregp 复制到外部驱动器。 首先,我 cd 到 /home 目录作为 pwd,然后输入 'cp -av gregp /run/media/.../externaldrive/
正如手册页所示,-a 选项与 -dR --preserve 相同,因此我可以保留时间戳、所有权和链接。 有时我想知道我上次编辑文件的时间。 通过转到 /home 目录,我还将复制各种配置文件和目录,例如 .bashrc 和 .kde

Greg,谢谢你的评论。

我喜欢你关于升级前备份的想法。我通常使用 tar 来做,但下次我可能会使用 cp!

回复 ,作者是 Greg P

非常有趣和有用!
另请指出,当你运行

cp -r -u -v Misc /media/clh/4388-D5FE

该命令会将 "source" 中不存在于 "destination" 中的文件,以及那些存在但不同的文件复制过去。
例如,如果你的 source 中有一个名为 "article.md" 的文件,并且 destination 中也存在该文件。
如果你修改了源文件,当你运行该命令时,更新后的源文件也会被写入到 destination 中。

祝您编程愉快!

谢谢你的评论,Victorhck。 很棒的观点! 如果源树中存在较新版本时,也可以使用其他的“创建备份”功能,那就更好了,但我认为这是不可能的。

非常感谢您将这篇文章翻译并重新发布到西班牙语网站上。 请在您的署名中注明原始文章的许可协议为 CC BY-SA 4.0。 再次感谢!

回复 ,作者是 victorhck

感谢分享。 如果我需要它,我会考虑的。 Linux 太棒了。

Iosvani 非常感谢您的评论。 我可以补充一点,Linux 如此棒的一个原因是因为像您这样的人在这个伟大的网站上做出的贡献!

回复 ,作者是 iogarchi

Creative Commons License本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
© . All rights reserved.