如何复制符号链接?

Bas*_*evs 211 linux symbolic-link command-line cp

我有包含一些符号链接的目录:

user@host:include$ find .. -type l -ls
4737414    0 lrwxrwxrwx   1 user group       13 Dec  9 13:47 ../k0607-lsi6/camac -> ../../include
4737415    0 lrwxrwxrwx   1 user group       14 Dec  9 13:49 ../k0607-lsi6/linux -> ../../../linux
4737417    0 lrwxrwxrwx   1 user group       12 Dec  9 13:57 ../k0607-lsi6/dfc -> ../../../dfc
4737419    0 lrwxrwxrwx   1 user group       17 Dec  9 13:57 ../k0607-lsi6/dfcommon -> ../../../dfcommon
4737420    0 lrwxrwxrwx   1 user group       19 Dec  9 13:57 ../k0607-lsi6/dfcommonxx -> ../../../dfcommonxx
4737421    0 lrwxrwxrwx   1 user group       17 Dec  9 13:57 ../k0607-lsi6/dfcompat -> ../../../dfcompat
Run Code Online (Sandbox Code Playgroud)

我需要将它们复制到当前目录。生成的链接应该独立于它们的原型,并直接指向它们的目标对象。

  • cp -s 创建指向不适当行为的链接的链接。
  • cp -s -L 拒绝将链接复制到目录
  • cp -s -L -r 拒绝将相对链接复制到非工作目录

我该怎么办?

小智 235

cp --preserve=links
Run Code Online (Sandbox Code Playgroud)

从手册页:

   --preserve[=ATTR_LIST]
          preserve  the   specified   attributes   (default:   mode,owner-
          ship,timestamps),  if  possible  additional attributes: context,
          links, xattr, all
Run Code Online (Sandbox Code Playgroud)

就个人而言,我cp -av 用于大部分重度复制。这样,我可以保留所有内容 - 甚至是递归的 - 并查看输出。当然,这只是个人喜好。

至于为什么您的其他选项没有达到您的预期,请-s创建链接而不是复制并-L按照源中的链接查找要复制的文件而不是复制链接本身。

  • 在 Mac 上?使用`cp -a` (48认同)
  • +1 为 `-a` 选项。呵呵,我已经无数次在`cp` 的联机帮助页中查找选项,但我一定总是浏览这个选项。到目前为止,我一直在使用 `-dpr`,但 `-a` 涵盖了所有这些,并保留了一些其他属性。如果我需要这些其他属性,我可能会再次查找 `--preserve` 选项并使用 `-dr --preserve=all`,这正是 `-a` 的含义!好吧,至少我现在知道 - `-a` 是完美的,这就是我从现在开始使用的。 (13认同)
  • 我在 redhat 上试过这个,但它不起作用 (8认同)
  • 您可能需要添加 `-R`,否则 cp 将跳过目录和指向目录的符号链接。 (3认同)
  • 这在 Cygwin 上不起作用。`--preserve=links` 还不够。它仍然说“cp:省略目录”。但是`-av` 奏效了。 (3认同)

Ign*_*ams 60

正如手册页所说,使用-P. 这个设置说:

-P, --no-dereference
       never follow symbolic links in SOURCE
Run Code Online (Sandbox Code Playgroud)

  • 在 Mac 上,`-P` 不适用于目录,所以我使用了 `cp -a` (13认同)
  • 谢谢,我已经在一年中的不同时间看到 3 次并从您的回答中受益。好像想不起来了! (4认同)
  • 这个“cp -P”与@kainosnous 投票最高的答案不同,对我来说很有效。谢谢! (3认同)

mru*_*cci 33

如果链接包含相对路径,那么复制链接不会调整相对路径。使用readlink, 和 switch-f递归跟踪,以获得链接的绝对路径。例如:

ln -s $(readlink -f old/dir/oldlink) new/dir/newlink
Run Code Online (Sandbox Code Playgroud)

如果保留相对路径是您想要-Pcp,那么正如 Ignacio Vazquez-Abrams 所说,您需要的选项是 。


Juh*_*uh_ 31

正如一些人评论的那样:

cp -a 
Run Code Online (Sandbox Code Playgroud)

效果很好。

来自男人:

-a    same as -dR --preserve=all

-R    copy directories recursively
-d    same as --no-dereference --preserve=links
--no-dereference   never follow symbolic links in SOURCE
Run Code Online (Sandbox Code Playgroud)

  • ...但前提是没有任何符号链接指向相对路径。 (3认同)

qua*_*ote 12

大多数时候,当我需要复制许多符号链接时,我实际上是在尝试镜像目录树。所以我想要符号链接和其他所有东西。

这对于仅复制几个符号链接来说是多余的,但是如果您实际上是在尝试复制整个树,这可能非常有用:

使用焦油

user@host:/cwd$ ( cd /path/to/src ; tar cf - . ) | ( cd /path/to/dest ; tar xf - )
Run Code Online (Sandbox Code Playgroud)

tar默认不解析符号链接,因此镜像副本中的符号链接将指向与原始树中相同的位置。

这个技巧利用子shell 将tar命令定位到要镜像的目录的根目录;如果您已经在srcdest目录中,则可以省略其中之一(以及相关的cd命令):

# already in src?
user@host:/src$ tar cf - . | ( cd /path/to/dest ; tar xf - )

# already in dest?
user@host:/dest$ ( cd /path/to/src ; tar cf - . ) | tar xf - 

# just need src/foo?
# this result will be a mirror copy at dest/foo 
user@host:/src$ tar cf - foo | ( cd /path/to/dest ; tar xf - )

# mirror to another system?
user@host:/src$ tar cf - . | ssh user@example.com '( cd /path/to/dest ; tar xf - )'
Run Code Online (Sandbox Code Playgroud)

同样,这并不适合每次您想要复制符号链接时,但这是一个非常有用的片段。


小智 11

我使用以下内容复制了一个非常大的目录。所有符号链接都被保留了下来,复制是递归完成的,我能够对这个过程有一些视觉反馈:

cp -Prv /sourcer_dir/* /target_dir
Run Code Online (Sandbox Code Playgroud)