使用Shell脚本递归复制目录

3
应该对这里的大牛来说是个简单的问题,尽管用文本解释很困难,但希望这很清楚。我有两个目录在一个运行某种unix系统的盒子上。我有一个脚本,想用它来将一个位置的所有文件和目录移动到另一个位置。
首先,让我们看一下这些目录的样子:
目录A:final/results/2012/2012-02/2012-02-25/name/files 目录B:test/results/2012/2012-02/2012-02-24/name/files 你会看到它们非常相似。我想做的是将Directory B的2012目录中的所有内容,递归地移动到Directory A的相同级别。所以你最终会得到: someproject/results/2012/2012-02/2012-02-25/name/files someproject/results/2012/2012-02/2012-02-24/name/files 等等。
我希望这个脚本是未来可靠的,这意味着我不想硬编码2012。此外,在月底时,你可能会有来自两个不同月份的数据,并且都需要复制到2012目录中。所以,这是我在shell脚本文件中使用的命令:
CONS="/someproject";
ROOT="/test";

/bin/cp -r ${ROOT}/results/* ${CONS}/results/*

但是结果却是这样的:
/final/results/2012/2012-02/2012-02-25/name/files

/final/results/2012/2012/2012-02/2012-02-24/name/files
可以清楚地看到,它比我想要的低一个级别。如果有人能理解我在尝试说明什么,并告诉我我的错误是什么,那就太好了。如果没有表述清楚,敬请谅解。我相信这是一个相当简单的修复问题,但我不确定该怎么做。Shell脚本编写并非我的强项。

2
为什么不使用 cp -r ${ROOT}/results ${CONS}/results 呢? - sgibb
2
你的cp命令中第二个不是一个好主意。它会扩展为目标目录中的目录列表,然后将所有内容复制到最后一个列出的目录中(因为这就是cp的作用)。去掉第二个,你就可以顺利进行了。 - zmccord
@zmccord 谢谢!我知道这只是一些小而愚蠢的东西,但正如我所说,编写脚本不是我的强项。它完美地解决了问题。如果你把它作为答案添加进去,我会接受它的。 - cardician
甚至第一个 * 也不需要。 - Perry
@sgibb 我尝试了这种方式,没有使用 *,但它并没有提供期望的结果。相反,它将另一个结果目录(以及其下的所有内容)添加到 A 主任的结果目录中。但是,如果不使用第二个 * 就可以完美地解决问题。还是谢谢你。 - cardician
2个回答

4

一位用户建议使用rsync,但这可能有些过度。

cp -rp可以完美地解决问题。如果你想移动文件,只需将整个目录移动--它和它下面的所有内容都会被移动。

唯一的真正问题在于原始脚本中命令行中终止符号*的使用。你不需要使用*,你只是想将目录传递给cp命令,而不是传递源中已有的所有文件的名称(更重要的是传递目的地)。


是的,正如另一个帖子评论中指出的那样,cp命令中的最后符号是问题所在。如果他没有发布答案,我将选择您的回答作为答案。然而,我已经尝试了两种方法,既不带,也只带第一个,但只有当我保留第一个并删除第二个*时才能获得所需的结果。 - cardician
这是因为 * 的意思是“所有不以.开头的文件”,在大多数情况下这意味着相同的事情——除非你有一个以.开头的文件名——所以如果我是你,除非你知道为什么要使用它,否则我会去掉 *。 - Perry

3

您也可以使用像rsync这样的工具来确保源和目标同步。

rsync -av ${ROOT}/results/ ${CONS}/results/

您指定了要“移动”文件,这意味着在复制后删除原始文件:
rsync -av --remove-source-files ${ROOT}/results/ ${CONS}/results/

如果你开始使用rsync,请务必阅读有关它如何处理尾部斜杠的手册页面。

这个脚本运行的平台上没有可用的应用程序。也许是Solaris?不确定。谢谢。 - cardician
Rsync 对于这种工作来说有些过头了。普通的 cp 或 mv 就可以了。rsync 用于在网络上同步文件,对于这样的工作很少需要使用它。 - Perry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接