103

I have a directory that contains symbolic links to other directories located on different media on my system:

/opt/lun1/2011
/opt/lun1/2010
/opt/lun2/2009
/opt/lun2/2008
/opt/lun3/2007

But the symbolic links show up as:

/files/2011
/files/2010
/files/2009
/files/2008
/files/2007

How can I perform an rsync that follows the symbolic links?

e.g.:

rsync -XXX /files/ user@server:/files/

4 Answers 4

140

The -L flag to rsync will sync the contents of files or directories linked to, rather than the symbolic link.

10
  • 1
    When I do this, all the receiver symbolic links get deleted and my sender starts re-sending the files.
    – ensnare
    Mar 10, 2011 at 16:40
  • 5
    Hi -- these are directories. I got this to work with the -K flag.
    – ensnare
    Mar 10, 2011 at 21:20
  • 6
    I'm sure SO is making me more stupid..
    – John Hunt
    Nov 7, 2014 at 11:53
  • 10
    To clarify, -LK if you want to follow both symlinked files and directories
    – Mahn
    Jul 14, 2016 at 21:14
  • 3
    Always be careful when following such suggestions. Test, test, and test before your carry out product run! -L itself will remove all symlinks on your receiver side!
    – HongboZhu
    Jul 5, 2019 at 10:16
35

You need both -L and -K if you have symlinks on both sides, e.g. you already had your 1st rsync done and want to update the backup using rsync.

    -L, --copy-links            transform symlink into referent file/dir
    -K, --keep-dirlinks         treat symlinked dir on receiver as dir

In such cases, if you use only -L, the symlinks on the receiver side will be wiped out and new real dir will be made.

1
  • 1
    This should have been the selected answer.
    – ychaouche
    Nov 16, 2020 at 9:45
22

Just ran into this problem. And if you want rsync to treat symlinked directories as directories, you want the K option

rsync -K /files/ user@server:/files/

1
  • You might also want to add the --copy-unsafe-links option Aug 2, 2016 at 16:25
0

This question is old, but I'll leave a more complete answer here in case anyone else has this issue.

Let's start with the simplest and most general approach. In almost all cases, the best option would be to use the -a (--archive) switch. This approach will "follow symlinks" and reproduce them, exactly, in the destination dir.

rsync -a /files/ user@server:/files/

Some background: the -a|--archive switch is an alias for the following switches: -rlptgD

  • (-r|--recursive): recurse into directories
  • (-l|--links): copy symlinks as symlinks
  • (-p|--perms): preserve permissions
  • (-t|--times): preserve times
  • (-g|--group): preserve group

and the -D switch is, itself, an alias of the following switches:

  • (--device): preserve device files (requires root)
  • (--specials): preserve special files

Using rsync with the -a switch will duplicate all file types, sub directories, and symlinks exactly as they exist in the source directory.

If, instead, you want symlinked files and dirs to be converted to actual files & dirs--while maintaining the sane archive settings included in "-a"--you can append the -L switch (so it will take precedence over -l or use -rLptgD).

rsync -aL /files/ user@server:/files/

This approach is, arguably, a safer/saner version of the -LK switches in other answers.

However, if the goal is to preserve internal symlinks (whose targets are within the source dir tree) and include the actual files and dirs when symlinks are external, then a different approach is needed. In bash (and related shells?) something like this would work:

#!/bin/bash
src="./source"
dest="./dest"
rsync -a --save-links ${src} ${dest}
abs_src="$(realpath -- ${src})"
for i in $(find ${src} -type l); do
  target="$(target="$(readlink -f -- $i)" && echo "${target%/*}")"
  while [[ $target && ( ! $abs_src -ef $target ) ]]; do target="${target%/*}"; done
  test ! ${target} && rsync -aL ${i} ${i/$src/$dest}
done
New contributor
Overtoad is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .