169

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

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 ответов10

188
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 следует по ссылкам в источнике, чтобы найти файл для копирования, а не копировать сами ссылки.

36

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

28

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

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

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

23

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

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
10

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

cp -Prv /sourcer_dir/* /target_dir
9

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

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

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

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

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

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
1

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

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

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 для получения дополнительных опций.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .