使用'cp'命令复制目录内容


33

如何将一个目录的所有内容复制到另一个目录中?

例如:

$ cd /home/newuser
$ cp -a /backup/olduser/* .

上面的问题是全局模式'*'匹配隐藏目录'。' 和'..',你最终得到'newuser'中的目录'olduser',以及内容。

你也可以这样做:

$ rmdir /home/newuser
$ cp -a /backup/olduser /home/newuser

但是如果newuser已经包含一些默认文件和目录呢?

使用基本的'cp'命令和shell将一个目录的内容移动到另一个目录的最简单,最正确,最容易记住和不搞乱的方法是什么?

Answers:


30

尝试:

cp -ra /backup/olduser/. /home/newuser

这很好,但我无法弄清楚它是如何工作的。我想这可能是因为我不知道如何...工作。小心解释一下?
bradley.ayers 2011年

这对我有用,但cp -r ./a b没有。知道为什么吗?
布里格

2
也适合我,但r不需要选项。该a选项意味着r
MountainX

1
-r参数在这一点似乎有点多余!
庆祝大师

23

两个目录a和b。

两者都有文件。

您位于包含a和b的目录中。

cp -r ./a b

-r =递归。


你不想 - 获得所有文件吗?
bw

7
-a参数与所有文件无关,它是归档的缩写,它将保留文件所有权,权限,访问时间等。-a参数(虽然非常有用)不是标准选项,并且有几个cp实现没有提供它。
theotherreceive 2009年

1
@mch:自动收录,因为你已经告诉cp复制目录a,并a/.somedotfile通过包含a。如果b存在,此命令将创建aat 的精确副本b/a
quack quixote 09年

2
简单方法:cp -R /some/dir/* /another/dir
n0pe 2011年

1
这将a / foo复制到b / a / foo而不是b / foo
Sparr

18

还要记住,默认情况下,如果第二个目录存在,则将第一个目录INTO复制到第二个目录。例如,cp -a a b如果b存在,则复制INTO b,即它将创建一个b。

如果它不是您想要的,并且您想将a的内容复制到b中(例如,将整个文件系统复制到挂载点时),请使用:

cp -a a/. b

如上一个答案。

还请注意,-a包含-r这样做-ar是多余的。


请问该怎么/.工作的?
bradley.ayers 2011年

a/.表示目录'a'的内容而不是目录本身,在大多数情况下它是同义词,但在使用时cp -r,它避免了cp默认行为(复制INTO b)。
Nicolas Bonnefon

很棒的提示,这正是我正在寻找的但却未能在其他地方找到 - 所有'foo / *'或'-r foo /'在极端情况下失败。
特纳2013年

@TimoHuovinen'。' 根本不是通配符。它实际上是“父”目录,'..'是祖父母。这意味着'/foo/./././././。' 是与'/ foo'相同的目录,'/ foo / bar / ..'与'/ foo'是同一目录。将它们视为内置于文件系统的硬链接。
quuxman 2014年

@quuxman谢谢你,当时我还没有意识到这一点。我要删除旧的评论,以免混淆人们。
Timo Huovinen 2014年

6

除非您认真重新配置了shell,否则globbing模式'*'与'。'不匹配。或''',因为您可以使用echo *进行验证。它所做的是省略名称以“。”开头的文件,因此您的方法将错过所有隐藏文件。您可以使用shell选项调整一些此行为,例如bash中的dotglob选项,但它不会是您正在寻找的可移植且可靠的选项。

如果您需要执行此操作超过一次或两次,我建议您使用精心设计的源和目标规范来查看rsync或unison(具体取决于具体需求)。

另一种方法是将源目录放在tarball中,并在现有目标目录上解压缩。


1
我使用这个:( cd /src/dir ; tar cf - . ) | ( cd /dest/dir ; tar xf - )... tar cf - .tar是源目录,包含dotfiles,并将其吐出到STDOUT,它被传送到STDIN tar xf -
嘎嘎quixote 09年

我认为OP的重点是如何引用以'。'开头的文件。但不是特别'。' 和'..'目录。上面有一个更优雅的解决方案,而不是使用rsync或其他一些复杂的程序。
quuxman 2014年

2

这将复制普通文件和隐藏文件,同时排除父目录(..):

cd /directory/to/copy
cp -r * .[^.]* /destination/directory

如果不排除父目录,则最终..也会得到目标目录中的所有内容。


1
但这仍然排除 ..(例如,.....super-hidden开头的名称。
斯科特

0

要复制以点开头的文件,请执行cp。* target /

最简单的就是两次执行cp命令。

正如Peter Eisentraut所说,正常的全球规则不包括..和。(嗯,如何结束这句话?;)

只需使用-r使其递归,并使用-i使cp询问您是否确实要覆盖文件。

cp -ri /backup/olduser/* /newuser/
cp -ri /backup/olduser/.* /newuser/

通常*不符合...,但如果您使用,则会发生.*。试试echo .*。您可以排除...使用以下模式:.[^.]*
mch于2009年

@mch:但.[^.]*仍然排除 ..(例如,.....super-hidden开头的名称。
Scott

0

这适用于从当前目录递归地复制除隐藏目录之外的所有文件和目录到以下地址:

cp -rf * ^.* 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.