1

Say we have a path on our directory like:

a/b/c/d/e

where c is actually a symlink,

a/b/c -> f

And f contains d/e.

Then when I run rsync -avzR, without the --copy-unsafe-links flag, it will still copy this "unsafe" link.

Expected:

a/b/c->f
f/d/e

when I run rsync -avzR a/b/c/d/e some_dir.

Actual output:

a/b/c/d/e

How can I get the expected output in this way?

closed as unclear what you're asking by roaima, Isaac, bahamat, shirish, Rui F Ribeiro Jun 3 '18 at 21:10

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    It's not clear to me how a/b/c relates to f or d/e. Can you elaborate please – roaima Jun 1 '18 at 19:20
  • 1
    Can you please show the full command you're running? (You don't show how you're specifying the path(s) to copy) Is "c" a relative or absolute symlink? – BowlOfRed Jun 2 '18 at 3:16
  • I can send a MVCE command next Monday. I'm out of town for now. – OneRaynyDay Jun 2 '18 at 4:03
1

Per man rsync (my emphasis):

-R, --relative

Use relative paths. This means that the full path names specified on the command line are sent to the server rather than just the last parts of the filenames. [If] you used

rsync -avR /foo/bar/baz.c remote:/tmp/

then a file named /tmp/foo/bar/baz.c would be created on the remote machine, preserving its full path. These extra path elements are called "implied directories" (i.e. the "foo" and the "foo/bar" directories in the above example).

Beginning with rsync 3.0.0, rsync always sends these implied directories as real directories in the file list, even if a path element is really a symlink on the sending side. This prevents some really unexpected behaviors when copying the full path of a file that you didn’t realize had a symlink in its path. If you want to duplicate a server-side symlink, include both the sym‐ link via its path, and referent directory via its real path. If you’re dealing with an older rsync on the sending side, you may need to use the --no-implied-dirs option.

So, the behaviour you experienced is expected.

How to overcome this? I have not tested this, but I think a viable workaround would be along the lines:

mkdir -p some_dir/a/b
rsync -avz a/b/ some_dir/a/b  # Trailing slash after first 'b'
rsync -avz a/b/c/f some_dir   # No trailing slash after 'f'

I would also recommend reading the SYMBOLIC LINKS section of the rsync man page.

  • Thank you for the answer, but unfortunately after running that I end up with the same result; the symlink is not respected. – OneRaynyDay Jun 1 '18 at 18:16
  • @OneRaynyDay, I have edited my answer. – sampablokuper Jun 1 '18 at 18:25
0

I can't replicate your behavior. I've created a script that sets up a directory and then copies it. It has a relative and an absolute symlink inside. With the options that you show (-avzR), it shouldn't descend into either one, but copy the link as a link.

I assume that I've misinterpreted some aspect of what you're trying. So you can add in to your question if you find what that is, or you can run this script and see if your behavior is different than I show.

Script:

#!/bin/sh
SRC=/tmp/syncsrc
DEST=/tmp/syncdest
rm -rf $SRC $DEST
mkdir -p $SRC/a/b
mkdir -p $SRC/f/d
touch $SRC/f/d/e
ln -s ../../f $SRC/a/b/c
ln -s $SRC/f $SRC/a/b/g
mkdir $DEST
rsync -avzRi $SRC/a $DEST

Output

sending incremental file list
cd+++++++++ /tmp/
cd+++++++++ /tmp/syncsrc/
cd+++++++++ /tmp/syncsrc/a/
cd+++++++++ /tmp/syncsrc/a/b/
cL+++++++++ /tmp/syncsrc/a/b/c -> ../../f
cL+++++++++ /tmp/syncsrc/a/b/g -> /tmp/syncsrc/f

And the destination is created with the symlinks inside

$ find /tmp/syncdest \( -type l -printf '%h/%f -> %l\n' \) -o -printf '%h/%f\n'
/tmp/syncdest
/tmp/syncdest/tmp
/tmp/syncdest/tmp/syncsrc
/tmp/syncdest/tmp/syncsrc/a
/tmp/syncdest/tmp/syncsrc/a/b
/tmp/syncdest/tmp/syncsrc/a/b/c -> ../../f
/tmp/syncdest/tmp/syncsrc/a/b/g -> /tmp/syncsrc/f

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