How to copy symbolic links?

188

49

I have directory that contains some symbolic links:

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

I need to copy them to the current directory. The resulting links should be independent from their prototypes and lead directly to their target objects.

  • cp -s creates links to links that is not appropriate behavior.
  • cp -s -L refuses to copy links to directories
  • cp -s -L -r refuses to copy relative links to non-working directory

What should I do?

Basilevs

Posted 2010-05-07T04:36:38.103

Reputation: 2 237

2cp -R on a mac – Mirko – 2015-05-06T19:23:24.527

10cp -d made the job on my side. – m-ric – 2014-03-24T17:08:07.963

Answers

212

cp --preserve=links

From the man page:

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

Personally, I use cp -av for most of my heavy copying. That way, I can preserve everything - even recursively - and see the output. Of course, that is just personal preference.

As to why your other options did not do what you expected, -s makes a link instead of copying and -L follows the links in the source to find the file to copy instead of copying the links themselves.

kainosnous

Posted 2010-05-07T04:36:38.103

Reputation: 2 388

11+1 for the -a option. Heh, I've looked up options in cp's manpage countless times, yet I must have always skimmed over this one. I have until now been using -dpr, but -a covers all of those, plus the preservation of a couple of other attributes. If I'd have needed these other attributes I would have probably looked up the --preserve option again and used -dr --preserve=all, which is exactly what -a is! Well at least I know now – -a is perfect and this is what I'll be using from now on. – James Haigh – 2014-08-20T03:00:11.157

3This didn't work on Cygwin. --preserve=links wasn't enough. It still said cp: omitting directory. But -av worked. – Chloe – 2015-08-19T22:23:33.677

@JamesHaigh on my mac, man cp says " -a Same as -pPR options. Preserves structure and attributes of files but not directory structure." That sounds pretty scary, like the main point of copying a folder structure is not preserved. What does it mean if not that it copies flat? – AnneTheAgile – 2016-11-01T20:45:38.033

on Ubuntu 16.04 --preserve=link doesn't do the trick. cp -a instead, succeeds. – MarcusJuniusBrutus – 2017-02-28T20:53:59.433

On redhat/CentOS, cp -a works. – Sapience – 2019-05-22T07:24:35.673

3You might need to add -R, because otherwise cp will skip directories and symlinks to directories. – Olivier 'Ölbaum' Scherler – 2013-04-19T08:25:41.123

8I tried this on redhat and it doesn't work – Mansuro – 2013-05-27T07:57:06.933

Just what I needed to copy between volumes on an Amazon Linux AMI. Perfect! – notacouch – 2013-07-22T21:50:11.963

43on a Mac? use cp -a – Steve Tauber – 2013-09-19T17:52:37.010

Properties look different. And unlike a regular link (as I see in /usr/bin e.g. java) I don't see the Link Target anymore when I open up the properties using Ubuntu GNOME Files or Nautilus or whatever it is I'm using – Crowie – 2014-02-14T11:02:45.307

47

Just as the man page says, use -P.

Ignacio Vazquez-Abrams

Posted 2010-05-07T04:36:38.103

Reputation: 100 516

This works, but my man page say "-P never follow symbolic links in SOURCE", which is not intuitively the same as "copy symlinks as symlinks to destination". ("never follow" makes it sound like it works in combination with -R) – R.M. – 2016-07-07T19:00:21.597

This cp -P unlike the top voted answer by @kainosnous works for me. Thanks! – tommy.carstensen – 2017-01-03T11:48:40.620

Works on Redhat. The accepted response not work ! – Phiber – 2017-04-21T15:59:24.770

9on Mac -P does not work on directories so I used cp -a – Steve Tauber – 2013-09-19T17:52:03.303

4Thanks, I've seen and benefited from your answer 3 times now different times over a year. Can't seem to remember it! – Siddhartha – 2014-05-01T16:52:03.417

30

If the links contain relative paths, then, copying the link will not adjust the relative path. Use readlink, with the switch -f to follow recursively, in order to get the absolute path of the link. For example:

ln -s $(readlink -f old/dir/oldlink) new/dir/newlink

If preserving the relative paths is what you want, than the option -P of cp, as said by Ignacio Vazquez-Abrams, is what you need.

mrucci

Posted 2010-05-07T04:36:38.103

Reputation: 8 398

1It may be a bad idea to dereference recursively if all you are trying to do is to convert symlinks from being relative to absolute. The recursion is not needed here, and sometimes chained symlinks are there for a reason. Symlinks are often used to specify choices or configuration options. For example, on my system there is a symlink chain /usr/share/dict/words -> /etc/dictionaries-common/words -> /usr/share/dict/british-english which specifies the preferred dictionary. If you were to recursively dereference this chain, the resulting symlink would ignore any future changes to this preference. – James Haigh – 2014-08-20T03:35:48.053

24

As a few have commented:

cp -a 

works well.

From the man:

-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

Juh_

Posted 2010-05-07T04:36:38.103

Reputation: 341

3... but only if none of the symlinks are to relative paths. – Michael Scheper – 2016-10-30T21:27:03.890

11

Most of the time, when I need to copy many symbolic links, I'm actually trying to mirror a directory tree. So I want the symlinks and everything else.

This is overkill for copying just a few symlinks, but if you're actually trying to copy an entire tree, this can be very useful:

Use tar.

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

tar doesn't resolve the symlink by default, so symlinks in the mirror copy will point to the same locations as those in the original tree.

This trick makes use of subshells to get the tar command into position at the root of the directory to be mirrored; you can leave one of them out (along with the associated cd command) if you're already in the src or dest directories:

# 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 - )'

Again, this isn't appropriate for every time you want to copy symbolic links, but it is a very useful snippet to know.

quack quixote

Posted 2010-05-07T04:36:38.103

Reputation: 37 382

1tar is definitely more portable than cp in my experience – don bright – 2017-08-31T01:31:14.483

11

I used the following to duplicate a really large directory. All symbolic links were preserved, the copy was done recursively and I was able to have some visual feedback of the process:

cp -Prv /sourcer_dir/* /target_dir

oarevalo

Posted 2010-05-07T04:36:38.103

Reputation: 211

4

Try: cp -pr symlink destination

[root@station1 temp]# ls -l
total 8
-rw-r--r-- 1 root root  0 Jul 27 18:40 abc
lrwxrwxrwx 1 root root 13 Jul 27 18:41 abc.link1 -> /tmp/temp/abc
[root@station1 temp]# cp -rp /tmp/temp/abc.link1 /tmp/temp/abc.link2
[root@station1 temp]# ls -l
total 12
-rw-r--r-- 1 root root  0 Jul 27 18:40 abc
lrwxrwxrwx 1 root root 13 Jul 27 18:41 abc.link1 -> /tmp/temp/abc
lrwxrwxrwx 1 root root 13 Jul 27 18:42 abc.link2 -> /tmp/temp/abc
[root@station1 temp]# 

OS - Centos 5 (Linux)

ebe0

Posted 2010-05-07T04:36:38.103

Reputation: 41

3

On Ubuntu when copying links and files in a directory:

cp --no-dereference --preserve=links

Greg

Posted 2010-05-07T04:36:38.103

Reputation: 297

6cp -d is the shorthand for this – hunse – 2016-05-30T18:29:48.567

1I think both cp -a and cp --preserve=links do more than the question is asking. As I understand it, this is the correct answer for anyone using cp, though with files only (no directories) like in the question, --no-dereference would have no effect. – palswim – 2019-02-04T06:10:40.240

2

Use -P option, as Ignacio Vazquez-Abrams wrote above. What he didn't mention is -P has no effect without -R. So you need at least cp -RP.

(The site doesn't let me to comment yet so I posted a separate answer.)

1234ru

Posted 2010-05-07T04:36:38.103

Reputation: 81

On an old solaris box my cp does not support -d. cp -rP worked for me; (idk the diff between -R and -r, -r works for me). – spioter – 2019-09-18T12:45:56.830

1

cp -s and cp -L are special commands. For your requirement, use none.

e.g. Copying a directory DIR containing a and a symbolic link b pointing to a.

  • cp -s DIR/* N/ creates a symbolic link instead of copying, N/a->../DIR/a (link) and N/b->(../DIR/b) which is link to a link
  • cp -L DIR/* N/ copies with link dereferencing, N/a, N/b (same as DIR/a)

What you need is N/a(=DIR/a), and N/b->../N/a; so just copy without dereferencing, using cp -P option. I believe this is also the default for cp.

  • -P no-dereference, preserve links
  • -d combines -P option with -p to preserve=mode,ownership,timestamps
  • -a combines -d option with -R to recursively copy directories

refer man cp or cp --help for more options.

Atif Hussain

Posted 2010-05-07T04:36:38.103

Reputation: 111