Como copiar a estrutura de diretórios sem remover os links simbólicos?

25

Eu preciso "instalar" um monte de arquivos em outro diretório, mantendo intacta a estrutura de diretórios dos arquivos de origem. Por exemplo, se eu tiver ./foo/bar/baz.txt indo para /var/www/localhost/webroot/ , quero que o resultado seja /var/www/localhost/webroot/foo/bar/baz.txt . rsync tem esse recurso em --relative , mas quando eu fiz isso, descobri que não era amigável com links 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

Então você vê que o link simbólico não é mais um link simbólico - os arquivos foram copiados para o lugar errado!

rsync também tem a opção --no-implied-dirs , que superficialmente parece fazer o que eu quero, mas só funciona como pretendo quando não faz um rsync recursivo, então eu tenho que:

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

Existe alguma maneira mais direta de realizar esse espelhamento de arquivos sem apagar diretórios de links simbólicos intermediários (com ou sem rsync)?

    
por kojiro 24.02.2014 / 22:04

4 respostas

42

Use a opção rsync -K ( --keep-dirlinks ). A partir do manpage:

 -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.
    
por 24.02.2014 / 22:22
15

Eu queria preservar meus links simbólicos como links simbólicos. Para isso você pode usar a opção -l.

    -l, --links                 copy symlinks as symlinks

Como eu estava copiando estruturas no OS X, achei isso útil.

    
por 29.05.2015 / 20:12
2

Como resposta que não é rsync , o utilitário tar pode executar essa tarefa. Use duas instâncias de tar em cada lado de um canal, o primeiro para consumir uma estrutura de diretório e o segundo para extraí-lo em outro lugar. A propriedade do arquivo da cópia provavelmente será alterada, enquanto os modos de permissão provavelmente permanecerão inalterados.

Muitos exemplos existem e encontrei as sugestões nesta resposta de forma relativamente rápida: link .

Editar
Um segundo exemplo (mais sucinto?): link .

    
por 25.02.2014 / 11:41
1

Por favor, use -a , pois implica -l como era suposto acima. Mas também contém outras opções importantes se você quiser uma cópia completa da fonte.

Além disso: Pelo que entendi a man page, -K é destinado a links simbólicos no lado do receptor. Eu não acho que essa deveria ser a resposta correta aqui.

    
por 06.11.2016 / 14:00