Comment copier des liens symboliques?

180

J'ai un répertoire qui contient des liens symboliques:

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

J'ai besoin de les copier dans le répertoire actuel. Les liens résultants doivent être indépendants de leurs prototypes et mener directement aux objets cibles.

  • cp -s crée des liens vers des liens dont le comportement n'est pas approprié.
  • cp -s -L refuse de copier des liens vers des répertoires
  • cp -s -L -r refuse de copier les liens relatifs dans un répertoire qui ne fonctionne pas

Que devrais-je faire?

Basilevs
la source
10
cp -dfait le travail de mon côté.
m-ric
2
cp -Rsur un mac
Mirko

Réponses:

201
cp --preserve=links

De la page de manuel:

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

Personnellement, je l’utilise cp -av pour la plupart de mes gros travaux de copie. De cette façon, je peux tout conserver - même de manière récursive - et voir la sortie. Bien sûr, ce ne sont que des préférences personnelles.

En ce qui concerne la raison pour laquelle vos autres options ne répondent pas à vos attentes, -scrée un lien au lieu de les copier et -Lsuit les liens dans la source pour trouver le fichier à copier au lieu de copier les liens eux-mêmes.

kainosnous
la source
3
Vous devrez peut-être ajouter -R, car sinon cp ignorera les répertoires et les liens symboliques vers les répertoires.
Olivier 'Ölbaum' Scherler le
8
J'ai essayé ceci sur redhat et ça ne marche pas
Mansuro
41
sur un Mac? utilisercp -a
Steve Tauber
11
+1 pour l' -aoption. Heh, j'ai regardé les options dans cpla page de manuel de Saintes fois, mais j'ai toujours dû survoler celle-ci. J'ai utilisé jusqu'à présent -dpr, mais -acouvre tout cela, plus la préservation de quelques autres attributs. Si j'avais eu besoin de ces autres attributs, j'aurais probablement encore regardé l' --preserveoption et l'utilisé -dr --preserve=all, ce qui est exactement ce qui -aest! Au moins, je sais maintenant - -ac’est parfait et c’est ce que je vais utiliser à partir de maintenant.
James Haigh
3
Cela n'a pas fonctionné sur Cygwin. --preserve=linksn'était pas suffisant. C'est toujours dit cp: omitting directory. Mais -avtravaillé.
Chloé
43

Comme le dit la page de manuel, utilisez -P.

Ignacio Vazquez-Abrams
la source
8
sur Mac -Pne fonctionne pas sur les répertoires alors j'ai utilisécp -a
Steve Tauber
4
Merci, j'ai vu et bénéficié de votre réponse 3 fois maintenant à différents moments en un an. Je n'arrive pas à m'en souvenir!
Siddhartha
Cela fonctionne, mais ma page de manuel dit "-P ne suit jamais les liens symboliques dans SOURCE", ce qui n’est pas intuitivement la même chose que "Copier les liens symboliques en tant que liens symboliques vers la destination". ("ne jamais suivre" donne l'impression que cela fonctionne en combinaison avec -R)
RM
Ce cp -Pcontrairement à la réponse par plus de votes des œuvres @kainosnous pour moi. Merci!
tommy.carstensen
Fonctionne sur Redhat. La réponse acceptée ne fonctionne pas!
Phiber
29

Si les liens contiennent des chemins relatifs, la copie du lien ne modifiera pas le chemin relatif. Utilisez readlink, avec le commutateur -fà suivre récursivement, afin d’obtenir le chemin absolu du lien. Par exemple:

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

Si la préservation des chemins relatifs est ce que vous voulez, que l'option -Pde cp, comme le dit Ignacio Vazquez-Abrams, est ce que vous avez besoin.

mrucci
la source
1
Ce peut être une mauvaise idée de déréférencer la référence de manière récursive si vous essayez uniquement de convertir les liens symboliques en liens absolus. La récursion n'est pas nécessaire ici, et parfois des liens symboliques chaînés sont là pour une raison. Les liens symboliques sont souvent utilisés pour spécifier des choix ou des options de configuration. Par exemple, sur mon système, une chaîne de liens symboliques /usr/share/dict/words -> /etc/dictionaries-common/words -> /usr/share/dict/british-englishspécifie le dictionnaire préféré. Si vous deviez déréférencer cette chaîne de manière récursive, le lien symbolique résultant ignorerait les modifications ultérieures apportées à cette préférence.
James Haigh
24

Comme quelques-uns l'ont commenté:

cp -a 

fonctionne bien.

De l'homme:

-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_
la source
2
... mais uniquement si aucun des liens symboliques ne concerne des chemins relatifs.
Michael Scheper
10

La plupart du temps, lorsque je dois copier de nombreux liens symboliques, j'essaie en fait de refléter une arborescence de répertoires. Donc, je veux les liens symboliques et tout le reste.

C'est excessif pour la copie de quelques liens symboliques, mais si vous essayez de copier un arbre entier, cela peut être très utile:

Utilisez du goudron .

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

tar ne résout pas le lien symbolique par défaut, de sorte que les liens symboliques dans la copie miroir pointent vers les mêmes emplacements que ceux de l'arborescence d'origine.

Cette astuce utilise des sous-shell pour mettre en miroir la commande tar à la racine du répertoire. vous pouvez en laisser un (ainsi que la commande cd associée ) si vous vous trouvez déjà dans les répertoires src ou 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 [email protected] '( cd /path/to/dest ; tar xf - )'

Encore une fois, cela ne convient pas à chaque fois que vous voulez copier des liens symboliques, mais c'est un extrait de code très utile à connaître.

Quack Quack
la source
1
le goudron est définitivement plus portable que cp selon mon expérience
don brillante
10

J'ai utilisé ce qui suit pour dupliquer un très grand répertoire. Tous les liens symboliques ont été préservés, la copie a été réalisée de manière récursive et j'ai pu obtenir un retour visuel du processus:

cp -Prv /sourcer_dir/* /target_dir
Oarevalo
la source
4

Essayez: 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
la source
3

Sur Ubuntu lors de la copie de liens et de fichiers dans un répertoire:

cp --no-dereference --preserve=links
Greg
la source
4
cp -dest le raccourci pour cela
Hunse
Je pense que les deux cp -aet cp --preserve=linksfont plus que la question se pose. Si je comprends bien, c’est la bonne réponse pour quiconque l’utilise cp, bien que le fait de ne traiter que des fichiers (pas de répertoires) comme dans la question --no-dereferencen’aurait aucun effet.
Palswim
2

Utilisez l' -Poption, comme Ignacio Vazquez-Abrams a écrit ci - dessus . Ce qu'il n'a pas mentionné est -Psans effet -R. Donc il faut au moins cp -RP.

(Le site ne me permet pas encore de commenter, alors j'ai posté une réponse séparée.)

1234ru
la source
Sur une vieille boîte solaris, mon cp ne prend pas en charge -d. cp -rP a travaillé pour moi; (idk le diff entre -R et -r, -r fonctionne pour moi).
spioter il y a
1

cp -s et cp -L sont des commandes spéciales. Pour votre besoin, n'utilisez aucun.

Par exemple, copier un répertoire DIR contenant a et un lien symbolique b pointant vers a.

  • cp -s DIR / * N / crée un lien symbolique au lieu de copier, N / a -> ../ DIR / a (lien) et N / b -> (../ DIR / b) qui est un lien vers un lien
  • cp -L DIR / * N / copies avec déréférencement de liens, N / a, N / b (identique à DIR / a)

Ce dont vous avez besoin, c'est N / a (= DIR / a) et N / b -> ../ N / a; il suffit donc de copier sans dereferencing, en utilisant l'option cp -P. Je crois que c’est aussi la valeur par défaut pour cp.

  • -P pas de déréférence, préserve les liens
  • -d combine l'option -P avec -p pour conserver le mode =, la propriété, l'horodatage
  • -a combine l'option -d avec -R pour copier récursivement les répertoires

se référer man cpou cp --helppour plus d'options.

Atif Hussain
la source