Как скопировать символические ссылки?


180

У меня есть каталог, который содержит несколько символических ссылок:

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

Мне нужно скопировать их в текущий каталог. Получающиеся ссылки должны быть независимы от их прототипов и вести непосредственно к их целевым объектам.

  • cp -s создает ссылки на ссылки, которые не соответствуют поведению.
  • cp -s -L отказывается копировать ссылки на каталоги
  • cp -s -L -r отказывается копировать относительные ссылки в нерабочий каталог

Что я должен делать?


10
cp -dсделал работу на моей стороне.
M-ric

2
cp -Rна маке
Мирко

Ответы:


201
cp --preserve=links

Со страницы руководства:

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

Лично я использую cp -av для большинства моих тяжелых копий. Таким образом, я могу сохранить все - даже рекурсивно - и посмотреть результат. Конечно, это всего лишь личные предпочтения.

Что касается того, почему другие ваши варианты не сделали того, что вы ожидали, вместо копирования создайте -sссылку и перейдите по ссылкам в источнике, чтобы найти файл для копирования вместо того, чтобы копировать сами ссылки.-L


3
Возможно, вам придется добавить -R, потому что в противном случае cp будет пропускать каталоги и символические ссылки на каталоги.
Оливье Ольбаум Шерлер

8
Я попробовал это на Redhat, и это не работает
Мансуро

41
на Mac? использованиеcp -a
Стив Таубер

11
+1 за -aопцию. Хех, я смотрел варианты в cpman-странице бесчисленное количество раз, но я, должно быть, всегда просматривал эту страницу. Я до сих пор использовал -dpr, но -aохватывает все это, плюс сохранение нескольких других атрибутов. Если бы мне понадобились эти другие атрибуты, я бы, наверное, --preserveснова посмотрел на эту опцию и использовал ее -dr --preserve=all, что и -aесть! Ну, по крайней мере, теперь я знаю - -aидеально, и это то, что я буду использовать с этого момента.
Джеймс Хей

3
Это не сработало на Cygwin. --preserve=linksне было достаточно Это все еще сказано cp: omitting directory. Но -avсработало.
Хлоя

44

Как написано на странице руководства, используйте -P.


8
на Mac -Pне работает с каталогами, поэтому я использовалcp -a
Стив Таубер

4
Спасибо, я видел и получил пользу от вашего ответа 3 раза, а теперь раз в год. Не могу вспомнить это!
Сиддхартха

Это работает, но моя страница руководства говорит: «-P никогда не переходите по символическим ссылкам в SOURCE», что интуитивно не то же самое, что «копировать символические ссылки в качестве символических ссылок на место назначения». («никогда не следуй» звучит так, как будто работает в сочетании с -R)
RM

Это, в cp -Pотличие от топового ответа @kainosnous, работает для меня. Спасибо!
tommy.carstensen

Работает на Redhat. Принятый ответ не работает!
Фибер

29

Если ссылки содержат относительные пути, то копирование ссылки не будет корректировать относительный путь. Используйте readlink, с переключателем, -fчтобы следовать рекурсивно, чтобы получить абсолютный путь ссылки. Например:

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

Если сохранение относительных путей является то , что вы хотите, чем вариант -Pс cp, как сказал Игнасио Васкес-Abrams, является то , что вам нужно.


1
Может быть плохой идеей рекурсивное разыменование, если все, что вы пытаетесь сделать, это преобразовать символические ссылки из относительных в абсолютные. Рекурсия здесь не нужна, и иногда по какой-то причине существуют цепные символические ссылки. Символьные ссылки часто используются для указания вариантов или параметров конфигурации. Например, в моей системе есть цепочка символических ссылок, в /usr/share/dict/words -> /etc/dictionaries-common/words -> /usr/share/dict/british-englishкоторой указывается предпочтительный словарь. Если бы вы рекурсивно разыменовали эту цепочку, полученная символическая ссылка проигнорировала бы любые будущие изменения этого предпочтения.
Джеймс Хей

24

Как некоторые прокомментировали:

cp -a 

работает хорошо.

От мужчины:

-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

3
... но только если ни одна из символических ссылок не относится к относительным путям.
Майкл Шепер,

11

Я использовал следующее, чтобы дублировать действительно большой каталог. Все символические ссылки были сохранены, копия была сделана рекурсивно, и я смог получить некоторую визуальную обратную связь с процессом:

cp -Prv /sourcer_dir/* /target_dir

10

В большинстве случаев, когда мне нужно скопировать много символических ссылок, я на самом деле пытаюсь отразить дерево каталогов. Поэтому я хочу символические ссылки и все остальное.

Это избыточно для копирования всего нескольких символических ссылок, но если вы на самом деле пытаетесь скопировать целое дерево, это может быть очень полезно:

Используйте смолу .

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

tar не разрешает символическую ссылку по умолчанию, поэтому символические ссылки в зеркальной копии будут указывать на те же места, что и в исходном дереве.

Этот трюк использует подоболочки, чтобы получить команду tar в корне каталога, который нужно отразить; вы можете оставить один из них (вместе со связанной командой cd ), если вы уже находитесь в каталогах src или dest :

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

Опять же, это не подходит для каждого случая, когда вы хотите скопировать символические ссылки, но это очень полезный фрагмент кода.


1
По моему опыту, tar определенно более переносим, ​​чем cp
Дон

4

Попробуйте: cp -pr символическая ссылка назначения

[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]# 

ОС - Centos 5 (Linux)


3

В Ubuntu при копировании ссылок и файлов в каталог:

cp --no-dereference --preserve=links

5
cp -dэто сокращение для этого
hunse

1
Я думаю и то, cp -aи cp --preserve=linksдругое, чем вопрос. Насколько я понимаю, это правильный ответ для любого cp, кто использует , хотя только с файлами (без каталогов), как в вопросе, не --no-dereferenceбудет иметь никакого эффекта.
Palswim

2

Используйте -Pопцию, как писал Игнасио Васкес-Абрамс выше . То, что он не упомянул -P, без эффекта не имеет -R. Так что тебе нужно как минимум cp -RP.

(Сайт пока не позволяет мне комментировать, поэтому я разместил отдельный ответ.)


На старой коробке соляриса мой cp не поддерживает -d. cp -rP работал на меня; (У меня есть разница между -R и -r, -r работает для меня).
Спиотер

1

cp -s и cp -L - это специальные команды. По вашему требованию не используйте ничего.

Например, копирование каталога DIR, содержащего a и символическую ссылку b, указывающую на a.

  • cp -s DIR / * N / создает символическую ссылку вместо копирования, N / a -> ../ DIR / a (ссылка) и N / b -> (../ DIR / b), которая является ссылкой на ссылку
  • cp -L DIR / * N / копирует с разыменованием ссылки, N / a, N / b (аналогично DIR / a)

Вам нужно N / a (= DIR / a) и N / b -> ../ N / a; так что просто скопируйте без разыменования, используя опцию cp -P. Я считаю, что это также по умолчанию для cp.

  • -P без разыменования, сохранить ссылки
  • -d объединяет опцию -P с -p для сохранения = режим, владение, метки времени
  • -a объединяет опцию -d с -R для рекурсивного копирования каталогов

обратитесь man cpили cp --helpдля большего количества вариантов.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.