Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I need to "install" a bunch of files to another directory keeping the directory structure of the source files intact. For example, if I have ./foo/bar/baz.txt going to /var/www/localhost/webroot/ I want the result to be /var/www/localhost/webroot/foo/bar/baz.txt. rsync has this capability in --relative, but when I did this I discovered it wasn't friendly to symlinks:

$ 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

So you see the symlink is no longer a symlink – the files were copied to the wrong place!

rsync also has the --no-implied-dirs option, that superficially seems to do what I want, but it only works as I intend when not doing a recursive rsync, so I have to:

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

Is there any more direct way to accomplish this mirroring of files without wiping out intermediate symlink directories (with or without rsync)?

share|improve this question
1  
What about rsync's option -K? –  angus Feb 24 at 21:16
    
@angus hah, I must've read the manual six times and didn't see that. That seems to work perfectly. Why don't you make that an answer? –  kojiro Feb 24 at 21:17
add comment

2 Answers

up vote 9 down vote accepted

Use rsync's option -K (--keep-dirlinks). From the 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.
share|improve this answer
add comment

As a non-rsync answer, the tar utility can perform this task. Use two instances of tar on either side of a pipe, the first to consume a directory structure and the second to extract it elsewhere. File ownership of the copy will likely change, while the permission modes will likely remain unchanged.

Many examples exist and I found the suggestions in this answer relatively quickly: http://unix.stackexchange.com/a/59108/34251.

Edit
A second (more succinct?) example: http://unix.stackexchange.com/a/19824/34251.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.