IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope:Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  AIX and UNIX  >

系统管理员工具包: 移动 UNIX 目录

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 中级

Martin Brown (mc@mcslp.com), 自由撰稿人, Consultant

2006 年 10 月 16 日

有时候,您需要将整个 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. 同时使用 id 选项

$ 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 工具作为目标。





回页首


直接通过网络进行复制

将典型的 tarcpio 命令的输出通过管道传递到远程 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 分发版中的标准组件,它可能更加合适。



参考资料

学习
  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文

  • 系统管理员工具包:查看本系列中其他的部分。

  • 系统管理员工具包: 时间和事件管理:这篇文章介绍了一些自动执行和安排任务的方法。

  • 在 Bash shell 中工作:这个教程提供了使用 Bourne Again Shell 进行工作的指南,包括各种自定义和扩展环境的方法。

  • Bash:Bash 是标准的 Bourne shell 的替代 shell,并且与之具有类似的语法,但同时具备大量的新特性,包括别名、作业控制以及文件和目录名自动完成。

  • 让 UNIX 和 Linux 一起工作:这篇文章为让传统的 UNIX 发布版和 Linux 一起工作提供了指南。

  • AIX and UNIX:想了解更多内容吗?developerWorks 的 AIX and UNIX 专区提供数百篇关于 AIX 和 UNIX 的文章以及入门级、中级和高级教程,将让您打开眼界。

  • developerWorks 技术事件与网络广播:跟踪最新的 developerWorks 技术事件与网络广播。

  • 播客:收听播客并保持与 IBM 技术专家同步。

获得产品和技术
  • IBM 试用软件:使用 IBM 软件开发您的下一个项目,可直接从 developerWorks 下载这些试用软件。


讨论


关于作者

Martin Brown 成为职业作家已经超过 7 个年头。他所撰写的书籍和文章涵盖了各种各样的主题。他所擅长的领域包括大量开发语言和平台——Perl、Python、Java™、JavaScript、Basic、Pascal、Modula-2、C、C++、Rebol、Gawk、Shellscript、Windows™、Solaris、Linux、BeOS、Mac OS/X 等等——和 Web 编程、系统管理与集成。他是 Microsoft® 的 Subject Matter Expert (SME) 以及 ServerWatch.com、LinuxToday.com 和 IBM developerWorks 的固定投稿人。他也是 Computerworld、The Apple Blog 及其他站点的博客。您可以通过 Martin Brown 的网站与他联系。




对本文的评价

太差! (1)
需提高 (2)
一般;尚可 (3)
好文章 (4)
真棒!(5)

建议?







回页首


Java 和所有基于 Java 的商标都是 Sun Microsystems, Inc. 在美国和/或其他国家的商标。

Linux 是 Linus Torvalds 在美国和/或其他国家的商标。

Microsoft、Windows、Windows NT 和 Windows 徽标是 Microsoft Corporation 在美国和/或其他国家的商标。

UNIX 是 The Open Group 在美国和其他国家/地区的注册商标。 其他公司、产品或服务的名称可能是其他公司的商标或服务标志。

IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款