¿Cómo copiar la estructura del directorio sin eliminar enlaces simbólicos?

27

Necesito "instalar" un montón de archivos en otro directorio manteniendo intacta la estructura de directorios de los archivos fuente. Por ejemplo, si tengo que ./foo/bar/baz.txtir /var/www/localhost/webroot/, quiero que sea el resultado /var/www/localhost/webroot/foo/bar/baz.txt. rsynctiene esta capacidad --relative, pero cuando hice esto descubrí que no era amigable con los enlaces simbólicos:

$ ls -ald /var/www/localhost/webroot/ | grep ^l
lrwxrwxrwx  1 www-data www-data     15 2014-01-03 13:45 media -> ../static/media
lrwxrwxrwx  1 root     root         13 2014-02-24 13:47 var -> ../static/var
$ rsync -qrR . /var/www/localhost/webroot/
$ ls -ald /var/www/localhost/webroot/ | grep var
drwxr-xr-x 3 root root 4096 2014-02-24 13:52 /var/www/localhost/webroot/var

Como puede ver, el enlace simbólico ya no es un enlace simbólico: ¡los archivos se copiaron en el lugar equivocado!

rsynctambién tiene la --no-implied-dirsopción, que superficialmente parece hacer lo que quiero, pero solo funciona como lo pretendo cuando no estoy haciendo un rsync recursivo, así que tengo que:

find . -type f -print0 | xargs -0I{} rsync -R --no-implied-dirs {} /var/www/localhost/webroot/

¿Hay alguna forma más directa de lograr esta duplicación de archivos sin eliminar directorios intermedios de enlaces simbólicos (con o sin rsync)?

kojiro
fuente

Respuestas:

42

Use rsyncla opción -K( --keep-dirlinks). Desde la página del manual:

 -K, --keep-dirlinks
      This  option  causes  the  receiving side  to  treat  a
      symlink  to  a  directory  as though  it  were  a  real
      directory, but only if it matches a real directory from
      the  sender.   Without   this  option,  the  receiver’s
      symlink  would  be deleted  and  replaced  with a  real
      directory.

      For example, suppose you  transfer a directory foo that
      contains a file file, but foo is a symlink to directory
      bar  on  the  receiver.  Without  --keep-dirlinks,  the
      receiver  deletes  symlink  foo,   recreates  it  as  a
      directory,  and   receives  the   file  into   the  new
      directory.   With --keep-dirlinks,  the receiver  keeps
      the symlink and file ends up in bar.

      One note  of caution:  if you  use --keep-dirlinks, you
      must  trust all  the symlinks  in the  copy!  If  it is
      possible  for an  untrusted  user to  create their  own
      symlink to  any directory,  the user  could then  (on a
      subsequent  copy)  replace  the  symlink  with  a  real
      directory and affect the  content of whatever directory
      the  symlink references.   For backup  copies, you  are
      better off using something like a bind mount instead of
      a symlink to modify your receiving hierarchy.

      See also  --copy-dirlinks for  an analogous  option for
      the sending side.
angus
fuente
16

Quería preservar mis enlaces simbólicos como enlaces simbólicos. Para eso puedes usar la opción -l.

    -l, --links                 copy symlinks as symlinks

Como estaba copiando frameworks en OS X, encontré esto útil.

Ben Flynn
fuente
3

Úselo -a, ya que implica -lcomo se supuso anteriormente. Pero también contiene otras opciones importantes si desea una copia completa de la fuente.

Además: según entiendo la página del manual, -Kestá destinada a enlaces simbólicos en el lado del receptor. No creo que esta sea la respuesta correcta aquí.

Christian Gut
fuente
2

Como no rsyncrespuesta, la tarutilidad puede realizar esta tarea. Utilice dos instancias tara cada lado de una tubería, la primera para consumir una estructura de directorio y la segunda para extraerla en otro lugar. La propiedad del archivo de la copia probablemente cambiará, mientras que los modos de permiso probablemente permanecerán sin cambios.

Existen muchos ejemplos y encontré las sugerencias en esta respuesta relativamente rápido: /unix//a/59108/34251 .

Editar
Un segundo ejemplo (¿más sucinto?): Https://unix.stackexchange.com/a/19824/34251 .

crw
fuente