Как скопировать структуру каталогов без удаления символических ссылок?

27

Мне нужно «установить» кучу файлов в другой каталог, сохраняя структуру каталогов исходных файлов. Например, если я ./foo/bar/baz.txtсобираюсь, /var/www/localhost/webroot/я хочу, чтобы результат был /var/www/localhost/webroot/foo/bar/baz.txt. rsyncимеет эту возможность --relative, но когда я сделал это, я обнаружил, что он не дружит с символическими ссылками:

$ 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

Таким образом, вы видите, что символическая ссылка больше не является символической ссылкой - файлы были скопированы в неправильное место!

rsyncтакже есть --no-implied-dirsопция, которая внешне, кажется, делает то, что я хочу, но она работает только так, как я собираюсь, когда не делаю рекурсивный rsync, поэтому я должен:

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

Есть ли какой-либо более прямой способ выполнить такое зеркалирование файлов без удаления промежуточных каталогов символических ссылок (с или без rsync)?

Кодзиро
источник

Ответы:

42

Используйте rsyncопцию -K( --keep-dirlinks). Из справочной страницы:

 -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.
ангус
источник
16

Я хотел сохранить свои символические ссылки как символические ссылки. Для этого вы можете использовать опцию -l.

    -l, --links                 copy symlinks as symlinks

Так как я копировал фреймворки на OS X, я нашел это полезным.

Бен Флинн
источник
3

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

Также: Как я понимаю, страница руководства -Kпредназначена для символических ссылок на стороне получателя. Я не думаю, что это должен быть правильный ответ здесь.

Кристиан Гут
источник
2

В качестве не- rsyncответа, tarутилита может выполнить эту задачу. Используйте два экземпляра tarс каждой стороны канала, первый для использования структуры каталогов, а второй для ее извлечения в другом месте. Владение файлом копии, скорее всего, изменится, а режимы разрешений останутся неизменными.

Существует множество примеров, и я нашел предложения в этом ответе относительно быстро: /unix//a/59108/34251 .

Изменить
второй (более краткий?) Пример: /unix//a/19824/34251 .

CRW
источник