有时候,您需要将整个 UNIX 目录树复制到相同系统中其他的位置或不同的系统。有许多种不同的方法可以完成这项操作,但并非所有的方法都可以保持信息数量不变或兼容于不同的系统。本文讨论了 UNIX 中各种可用的选项,以及如何最好地使用它们来完成相应的任务。

关于本系列

通常,UNIX 管理员都拥有一套常用的辅助进程管理的关键实用工具、诀窍和系统。本文提供了各种用于简化各个过程的关键实用工具、命令行链和脚本。这些工具中的一部分来自于操作系统,而大部分的诀窍则来源于长期的经验积累和减轻系统管理员的工作压力的要求。本系列文章主要专注于最大限度地利用各种 UNIX 环境中可用的工具,包括简化异类环境中的管理任务的方法。

使用 cp

如果您使用 -r 命令行选项递归到其子目录中,标准的 cp 命令可用于复制整个目录树。该选项将对非标准的文件执行未知的操作。有些 UNIX 变种和 GNU cp 工具支持 -R 选项,使用该选项可以正确地复制命名管道、链接和其他的文件。

对于最简单的应用,cp 命令可以将目录复制到具有不同名称的新目录(请参见清单 1)。

清单 1. cp 命令—将一个目录复制到具有不同名称的新目录

$ cp -r srcdir destdir

复制代码

然而,当在 cp 命令中指定源文件和目标位置时,您应该加以小心,因为其处理方式可能对结果有很大的影响。例如,假设您希望将目录 /home/mc 复制到目录 /export/home/mc。如果 /export/home/mc 不存在,那么清单 2 会将目录 /home/mc 复制到 /export/home/mc。

清单 2. 在 cp 命令中指定源文件和目标位置

$ cp -r /home/mc /export/home/mc

复制代码

然而,如果 /export/home/mc 已经存在,那么清单 2 会将目录 /home/mc 复制到这个目录中,并创建新的目录 /export/home/mc/mc。

要将一个目录中的内容复制到一个已有的目录中,可以选择源目录中的文件,如清单 3 所示。

清单 3. 将一个目录中的内容复制到一个已有的目录中

$ cp -r /home/mc/* /export/home/mc

复制代码

cp 工具有一个非常有用的选项,-p 命令行选项,它还可以确保维持每个文件的权限和所有权。

使用 tar

tar 命令最初用来将文件归档到磁带(确切地说,是磁带驱动器)。例如,您可以使用清单 4 中的命令,将当前目录中的文件复制到磁带上。

清单 4. 使用 tar 将当前目录中的文件复制到磁带

$ tar cf /dev/rmt0 .

复制代码

可以对清单 4 进行如下分析:

* c 选项创建一个新的存档。

* f 选项使用命令行中的下一个选项作为目标名称。在这个示例中,使用第一个原始磁带设备 (/dev/rmt0)。您还可以使用其中所有的信息创建一个 tar 文件。

* . 告诉 tar 将所有的文件和目录(以及当前目录下所有的文件和目录)添加到这个存档文件中。

然而,除了可以将文件和目录结构复制到磁带,您还可以使用 tar 将它们复制到一个文件。更有用的是,您可以将文件复制到标准输出,然后可以使用管道从标准输入中提取这些文件,并将它们从一个地方复制到另一个地方。通常在系统中复制和重新创建非标准的文件类型时,tar 命令更加可靠,因为 cp 命令不支持 -R 命令行选项。

例如,清单 5 显示了如何将文件从当前目录复制到一个已有的目录。

清单 5. 将文件从当前目录复制到一个已有的目录

$ tar cf - . | (cd DIR; tar xf - )

复制代码

可以对清单 5 进行如下分析:

* tar cf - . 对当前目录中的文件创建一个新的存档,输出到标准输出。

* cd DIR 更改了目录。请注意,这个目录在进行文件复制之前应该已经存在。

* tar xf - 从标准输入中提取文件。

* 通过使用圆括号将上面的两个部分括起来,可以有效地将它们作为一个而不是两个命令来处理,并且 cd 命令在提取存档之前进行。

* 两者之间的管道 (|) 将第一个 tar 的标准输出传入到第二个 tar 的标准输入,并且高效地将文件复制到一个并不存在的存档文件,然后再从其中提取文件。

如果您显式地指定了路径,那么 tar 命令可以保持存档中所包含的文件的完整路径。清单 6 使用显式的路径将文件复制到存档中,这意味着,不能将这些文件提取到其他的地方,只能返回到它们的初始位置。

清单 6. 显式地指定路径

$ tar cf  myhome.tar /home/mc

复制代码

有些 tar 变种可以去掉开头的正斜杠,这使得您可以将文件提取到任何位置。要确保总可以将文件放到需要的位置,您应该使用清单 7 中的命令从当前目录中添加文件。

清单 7. 从当前目录添加文件

$ cd /home/mc

$ tar cf myhome.tar .

复制代码

与 cp 相比,tar 命令有一个优点,那就是通过添加 v 命令行选项以打开详细模式,您可以在将文件从源复制到目标的过程中监视文件的传输。通常,最好是在提取文件的 tar 命令中使用这个选项,而不是在创建存档的 tar 命令中使用,因为它可以确保正确地对文件进行复制,而不是证实对其进行了正确的读取(请参见清单 8)。

清单 8. 添加 v 命令行选项

$ tar cf - .|(cd /tmp/mc; tar xvf -)

./

./.bash_aliases

./.bash_history

./.bash_path

./.bash_profile

./.bash_vars

./.bashrc

./xmlsimple.pl

./rest.xml

...

复制代码

请注意,如果系统的 tar 不支持长路径名,那么它可能不支持更新的 tar 格式。GNU tar 支持新的 tar 格式,并且支持长的或者非常深的路径名。

缺省情况下,大多数 tar 变种可以正确地复制和重新创建文件和目录,并保持相同的所有权和权限信息,然而,如果作为 root 用户运行,那么有些变种会改写这个信息,并在提取文件的时候改变其所有权。您可以使用 p 选项确保保持相应的权限和所有权(请参见清单 9)。

清单 9. 使用 p 选项

$ tar cpf - .|(cd /tmp/mc; tar xvpf -)

复制代码

最后,您还可以通过扩展这个命令的后半部分(请参见清单 10),创建一个新的目录作为复制这些文件的目标。

清单 10. 创建一个新的目录作为复制文件的目标

$ tar cpf - .|(mkdir /tmp/mc; cd /tmp/mc; tar xvpf -)

复制代码

就其本身而言,tar 是一种非常有用的工具,可用于复制文件和目录结构。然而,当您使用它通过网络来复制文件时,才能真正体现出它的价值。在研究这种诀窍之前,先来使用另一种存档工具 cpio,这也是一种基本的处理方法。

使用 cpio

cpio 工具类似于 tar 工具,但是除了接受指定的文件或目录之外,您必须为它提供一个文件列表。如果您只希望复制特定的文件,那么这个工具可能更加实用。例如,要创建一个包含特定目录的 cpio 存档,您可以使用清单 11 中的命令。

清单 11. 创建包含特定目录的 cpio 存档

$ ls ./dira ./dirc |cpio -ov > diranc.cpio

复制代码

这个命令的 ls 部分输出将要复制的文件列表(在本示例中是两个目录中的内容)。后半部分是用于将它们复制到存档中的 cpio 命令。对这个命令进行分析,其中包括两个选项:

* o 选项将文件复制到存档。

* v 选项在复制文件时显示文件列表,这可用于对复制过程进行确认。

通过将 cpio 的输出重定向到一个新的文件,可以创建实际的存档。

上面的命令存在一定的局限,它只能复制那些显式列出的文件。要复制整个目录,最好的方法是使用 find 命令(请参见清单 12)。

清单 12. 使用 find 命令复制整个目录

$ find . |cpio -ov >archive.cpio

复制代码

要从 cpio 存档中提取,可以使用 i 命令行选项。您还应该使用 d 选项确保重新创建那些在存档中存在、而在目标结构中不存在的目录。同时使用这两个选项,您可以将文件从一个目录复制到另一个目录,如清单 13 所示。

清单 13. 同时使用 i 和 d 选项

$ find . |cpio -ov |(cd /tmp/mc; cpio -idv)

.

./.bash_aliases

./.bash_history

./.bash_path

./.bash_profile

./.bash_vars

./.bashrc

./xmlsimple.pl

./rest.xml

46 blocks

.

.bash_aliases

.bash_history

.bash_path

.bash_profile

.bash_vars

.bashrc

xmlsimple.pl

rest.xml

46 blocks

复制代码

因为在这个命令的两个部分中都使用了详细模式,所以可以确认创建的和提取的存档的大小是否相同。在本示例中,这两项操作都使用了 46 个块。

请注意,如果目标中的文件具有相同的、或更新的修改时间,那么 cpio 不会覆盖这些文件。

通过网络进行复制

在 UNIX 中通过网络传输文件的常用方法是使用网络文件系统 (NFS) 装入远程目录,然后进行与本地目录之间的复制。这是一种比较简单的解决方案,但对于各种各样的情况,它并不总是可行的或实用的。

通过网络复制文件的最简单的方法之一是使用 tar 或 cpio 创建存档文件,然后可以通过网络传输这个存档文件。这种方法具有一些优点,比如可以自由选择如何以及何时进行文件的复制,但它也有一些缺点,包括复制过程的复杂性,以及在源系统中创建存档和将该存档复制到目标系统时保存完整的重复文件的磁盘空间需求。

正如您所看到的,创建存档非常简单:

清单 14. 创建一个存档

$ tar cf mydir.tar .

复制代码

然后,您可以使用合适的方法对该文件进行复制,例如,使用 cp 和 NFS 复制该文件,或使用 FTP 或 SFTP 将该文件传输到远程系统。

然而,使用存档文件的方法并不是一种特别高效的方法。您可以通过压缩来提高其效率。

使用压缩

如果您使用 cpio 或 tar 创建存档文件,并通过慢速的连接对文件进行复制(例如 WAN 或 Internet,而不是 LAN 环境),那么可以在传输存档文件前对其进行压缩处理,这样会节省传输的时间。可以根据您所需的压缩级别选择合适的压缩格式。

使用存档的方法非常简单。您可以选择在创建存档之后对其进行压缩,如清单 15 所示。

清单 15. 在创建存档之后对其进行压缩

$ tar cf mydir.tar .

$ bzip2 mydir.tar

复制代码

要完成这项操作,您还可以使用管道生成存档的压缩版本(请参见清单 16)。

清单 16. 使用管道生成存档的压缩版本

$ tar cf - .| bzip2 >mydir.tar.bz2

复制代码

清单 16 中方法的优点是,它可以使用各种版本的 tar、cpio 或任何其他的存档工具。它还适用于各种不同的平台,而这些平台中的不同变种的 tar 可能并不一定支持联机压缩处理。如果安装了 GNU 版本的 tar,那么您可以使用带 z 命令行选项的 tar 命令,这样就可以使用 Gzip 进行压缩处理(请参见清单 17)。

清单 17. 使用带 z 命令行选项的 tar

$ tar zcf mydir.tar.gz .

复制代码

在系统之间进行目录复制的另一种方法是,使用清单 16 中所示的管道解决方案,但需要使用远程 Shell 工具作为目标。

直接通过网络进行复制

将典型的 tar 或 cpio 命令的输出通过管道传递到远程 Shell 中,如远程 Shell (rsh) 或安全 Shell (ssh),您可以直接通过网络进行复制。使用哪一种远程 Shell 技术,完全取决于您的环境中可以使用的 Shell。前者 (rsh) 是一种标准的远程 Shell 系统,它提供了基本的身份验证安全性,但不提供加密功能,而后者 (ssh) 提供了基本的身份验证和数据加密功能。

这两种方法使用了相同的基本命令行结构(请参见清单 18)。

清单 18. 直接通过网络进行复制

$ tar cf - ./*|rsh remotehost tar xf - -C /remotedir

复制代码

除了在远程系统中执行目标 tar 命令之外,这个命令类似于本地化的 tar。因为在这两个命令之间使用了管道,所以系统能够正常工作。

请记住,根据远程 Shell 的配置,在远程计算机上进行身份验证时,您可能需要输入密码。ssh 可能也会使用相同的处理方法。清单 19 指定了用户/主机的组合。

清单 19. 指定在远程计算机上进行身份验证所使用的用户/主机的组合

$ tar cf - ./*|ssh user@remotehost tar xf - -C /remotedir

复制代码

为了在慢速的连接上实现更好的性能,您应该使用压缩处理,如清单 20 所示。

清单 20. 在直接通过网络进行复制的过程中使用压缩处理

$ tar czf - ./*|ssh user@remotehost tar xzf - -C /remotedir

复制代码

rsh 和 ssh 具有比较简单的命令行格式,这使得从远程系统中进行复制的过程变得更加简单。例如,rcp 与 rsh 非常接近,您可以使用清单 21 中的命令。

清单 21. 使用 rcp 复制远程系统中的文件

$ rcp -r filename remotehost:/remotedir

复制代码

您必须使用 -r 命令行选项,这样可以对目录进行递归地复制。

scp 命令非常接近于 ssh,它使用了相同的结构(请参见清单 22)。

清单 22. 使用 scp

$ scp -r filename remotehost:/remotedir

复制代码

通过网络进行同步

上面所有的解决方案都主要考虑对文件的复制,包括本地的以及通过网络的复制。然而,它们在每次进行复制操作时,都会复制整个目录结构,而这并不总是必需的。有时,您只需要复制那些在上次复制操作之后进行过更改的文件,从本质上说是进行同步,而不是彻底的再次复制。

如果您使用 tar 或 cpio,那么通过显式地指定存档中需要包含的文件,您可以实现基于时间的同步。例如,如果您使用 cron 来运行同步任务,那么您可以使用下面的命令,创建仅包括在前一天进行了更改的文件的存档(请参见清单 23)。

清单 23. 创建仅包括在前一天进行了更改的文件的存档

$ tar cf archive.tar `find . -mtime -1 -type f`

复制代码

find 命令可以查找在前一天进行了更改的文件。我仅选择了文件,因为如果包含目录,那么 tar 将包含该目录中所有的文件,这样一来,存档文件中将包含比所需要的更多的信息。

要实现更健壮的同步操作,您可以使用 rsync 工具,它是一种免费的软件实用工具,可以高效地通过网络交换文件。对于复制和同步文件,尤其是在较慢的连接中,rsync 工具可能是一种有效的方法。

总结

当您在 UNIX 中复制文件和目录树时,无论是在相同的系统中还是在通过各种类型的网络连接的不同系统之间,都可以选择使用各种各样的工具和方法。究竟使用哪一种工具,取决于实际的情况和环境。我倾向于使用 tar,因为它是我使用过的最能够兼容于各种不同 UNIX 系统的工具。对于使用 Linux® 环境的用户来说,scp 工具是大多数 Linux 分发版中的标准组件,它可能更加合适。

linux 移动目录树到子目录中,Linux系统管理员工具包: 移动Linux/UNIX目录相关推荐

  1. linux内核教学的全套视频,中科大老师全程讲解Linux内核分析视频教程《附加介绍+总结》共23节课...

    中科大老师全程讲解Linux内核分析视频教程<附加介绍+总结>共23节课" F4 u& {+ T) p5 G' W  ]; o% m 2 q: ]. j8 I; q' D ...

  2. 解决VS2010子目录中的.cpp文件引用上一级目录的stdafx.h找不到定义的问题

    Source目录 |-- stdafx.h |--Util目录 |--Util.h |--Util.cpp 现在的发现Util.cpp各种变量的定义全是红色波浪线,找不到定义,但是却能够编译过 问题就 ...

  3. linux的一个find命令rm删除某目录下所有子目录 中的某类文件

    一前言 当前目录下含有许多的子目录 ,子目录 下又包含不定深度的子目录 .所有子目录 中都有一个文件test.file,需要对所有的test.file文件予以删除 二解决方案 使用find命令 将当前 ...

  4. 在windows上linux命令行,如何在Windows中通过Cygwin来使用Linux命令行

    添加Cygwin路径到Windows环境变量 安装完成以后在桌面上会出现一个Cygwin的图标,通过它可以打开Cygwin终端. 终端会以C:Cygwin主目录作为开始,但是那可能没有用处,因为你可能 ...

  5. linux开源文档管理系统_Linux中的系统管理员问题 免费和开源软件

    linux开源文档管理系统 根帐号 (Root Account) The "root" account is the most unrestrictive account on a ...

  6. Linux目录树与文件系统(挂载)

    Linux目录树与文件系统(挂载) 目录树结构(directory tree) 目录树架构就是以根目录为主,然后向下呈现分支状的目录结构的一种文件架构.整个目录树最重要的就是那个根目录(root di ...

  7. Linux——目录树(directory tree)

    在 Linux 底下,所有的文件与目录都是由根目录开始的!那是所有目录与文件的源头- 然后再一个一个的分支下来,有点像是树枝状啊-因此,我们也称这种目录配置方式为:『目录树(directory tre ...

  8. 工作中你应该掌握的 linux 命令大全

    作为码农,工作中你一定离不开使用 linux 命令,linux 命令繁多,学习起来确实很累,所以在工作的两年多的时间里,我把自己平时遇到的一些命令都零零碎碎的记录下来,正好这几天有时间对原先的记录做一 ...

  9. linux目录表及功能n鸟哥,鸟哥linux私房菜_笔记_Linux的文件权限与目录配置

    5.1 使用者与群组 1. 文件拥有者: 2. 群组概念: 3. 其他人的概念: Linux 使用者身份与群组记录的文件 默认的情况下,所有的系统上的帐号与一般身份使用者,还有那个root的相关信息, ...

最新文章

  1. Linux 设置 Swap 空间
  2. java juc exchanger_JUC工具类实例
  3. java中File类应用:遍历文件夹下所有文件
  4. 如何使用 Istio 进行多集群部署管理(一)
  5. 周五尾盘上涨,配合周末消息,周一套人的经典实例
  6. 深度为你解答怎么避免域名被微信拦截,微信域名防封需要注意哪些问题?
  7. kali局域网扫描ip_kali 扫描局域网的QQ
  8. Linux基础知识 | vi编辑器
  9. 金山电脑公司总经理雷军(转载)
  10. 发现一款牛逼的 IDEA 插件:检测代码漏洞,一键修复!
  11. java计算机毕业设计雁门关风景区宣传网站源码+系统+mysql数据库+lw文档
  12. 灰度图片及彩色图片像素点统计及显示
  13. 楼市回暖有赖于经济复苏
  14. 《汇编语言》王爽(第四版)第八章 实验7
  15. Appstore商店排名前十的威客应用!
  16. 服务器机架位置,服务器的安装与机架的使用
  17. 音响发烧友福音!亚马逊中国“国际品质悦听馆”上线
  18. 软件工程的性能测试怎么写,软件工程——数独 性能测试2(示例代码)
  19. poi-tl生成word多张图表及图片
  20. Matlab 遗传算法优化BP神经网络

热门文章

  1. 【PC工具】更新在线流程图绘制工具bullmind,免费云存储流程图绘制,可直接粘贴图片...
  2. 通过 PSO实现TSP问题优化
  3. Android Java 8使用Lamda报错:Execution failed for task :app:transformJackWithJackForDebug - Android?...
  4. 学习 git clone 几种不同的协议
  5. 【ELK】ELK集群搭建(ElasticSearch Logstash Kinaba)
  6. Android-6步教你自定义View
  7. 新一代的树莓派3版本——Raspberry Pi 3 发布了
  8. 关于控件ID的试验(涉及MasterPage)
  9. 广播等风暴的解决办法
  10. 算法提高课-图论-单源最短路的综合应用-AcWing 1135. 新年好:dijkstra和dfs暴搜结合