1. Overview

rsync is a commonly used file synchronization tool. When we use rsync to transfer a file, the behavior is similar to the cp command – the file is copied to the destination directory.

As we know, cp copies the symbolic links (symlinks) in the source directory as symlinks to the destination directory. In this tutorial, we’ll discuss copying symlinks using rsync.

2. Analyzing the Problem

Let’s begin with an example. Suppose have a directory, source_directory:

$ pwd
/home/alice
$ ls –l source_directory/
total 0
-rw-r--r-- 1 alice alice  6 May 12  8:35 file1
lrwxrwxrwx 1 alice alice  5 May 12  8:35 flink1 -> file1
lrwxrwxrwx 1 alice alice 10 May 12  8:35 flink2 -> /tmp/file2
lrwxrwxrwx 1 alice alice 25 May 12  8:35 flink3 -> ../source_directory/file1
lrwxrwxrwx 1 alice alice 34 May 12  8:35 flink4 -> /home/alice/source_directory/file1

Let’s understand the contents of source_directory:

  • file1: a regular file
  • flink1: a relative symlink pointing directly to file1
  • flink2: an absolute symlink pointing to a file in a different directory, /tmp/file2
  • flink3: a relative symlink pointing indirectly to file1
  • flink4: an absolute symlink pointing to file1

Now, let’s try to copy the contents of source_directory to another directory, destination_directory, using rsync:

$ rsync source_directory/* destination_directory
skipping non-regular file “flink1”
skipping non-regular file “flink2”
skipping non-regular file “flink3”
skipping non-regular file “flink4”

We didn’t use any options of rsync. It seems that we couldn’t copy any of the symlinks according to the output of rsync. Let’s check the contents of destination_directory:

$ ls –l destination_directory/
total 0
-rw-r--r-- 1 alice alice 6 May 12  8:35 file1

As it’s apparent, we could only copy the regular file, file1. Our objective is to also copy the symlinks.

3. Using the -l Option

We can use the -l option of rsync for copying symlinks. rsync copies the symlinks in the source directory as symlinks to the destination directory using this option.

Let’s use the -l option to copy the contents of source_directory to destination_directory:

$ rm -f destination_directory/* 
$ rsync -l source_directory/* destination_directory/
$ ls -l destination_directory/
total 0
-rw-r--r-- 1 alice alice  6 May 12  8:35 file1
lrwxrwxrwx 1 alice alice  5 May 12  8:35 flink1 -> file1
lrwxrwxrwx 1 alice alice 10 May 12  8:35 flink2 -> /tmp/file2
lrwxrwxrwx 1 alice alice 25 May 12  8:35 flink3 -> ../source_directory/file1
lrwxrwxrwx 1 alice alice 34 May 12  8:35 flink4 -> /home/alice/source_directory/file1

Copying the symlinks is successful in this case. rsync copied file1 to destination_directory. flink1 is again a symlink to file1 in destination_directory. The absolute symlinks flink2 and flink4 point to the files  /tmp/file2 and /home/alice/source_directory/file1 just like the ones in source_directory.

However, flink3 points to ../source_directory/file1, not ../destination_directory/file1. Although flink3 in source_directory points to file1 in the same directory, rsync treated the symlink as pointing to an outside directory because of the double dot (..) in the symlink path. So, it points to ../source_directory/file1 in destination_directory.

We can also use the –links option instead of -l. Both options are the same.

The -a or –archive option of rsync can also be used for copying symlinks. This option is a collection of several other options of rsync. It includes the -l option. 

Although we copied only symlinks to files in our example, we can also copy symlinks to directories in the same way. However, we must use the –r option of rsync for copying directories.

The -l option isn’t the only option of rsync for copying symlinks. It has several other options. Let’s look at some of them.

If we just want to copy the symlinks pointing inside the destination directory, we can use the –safe-links option. rsync also ignores any absolute symlinks in this case:

$ rm –f destination_directory/*
$ rsync –l –-safe-links source_directory/* destination_directory/
$ ls -l destination_directory/
total 0
-rw-r--r-- 1 alice alice  6 May 12  8:35 file1
lrwxrwxrwx 1 alice alice  5 May 12  8:35 flink1 -> file1

As we see, rsync didn’t copy the symlinks flink2, flink3 and flink4. It only copied flink1 because it’s a symlink pointing to file1 inside the destination directory. As flink3 would point to ../source_directory/file1 which is outside the destination directory, rsync didn’t copy flink3. It didn’t copy flink2 and flink4 either as they’re absolute symlinks.

The –copy-unsafe-links option is another available option. When we use this option, rysnc treats symlinks that point outside the source directory like regular files:

$ rm –f destination_directory/*
$ rsync –l –-copy-unsafe-links source_directory/* destination_directory/
$ ls -l destination_directory/
total 0
-rw-r--r-- 1 alice alice  6 May 12  8:35 file1
lrwxrwxrwx 1 alice alice  5 May 12  8:35 flink1 -> file1
-rw-r--r-- 1 alice alice  0 May 12  8:35 flink2
-rw-r--r-- 1 alice alice  6 May 12  8:35 flink3
-rw-r--r-- 1 alice alice  6 May 12  8:35 flink4

As we see, flink1 was copied as a symlink to file1 as before. However, flink2, flink3 and flink4 aren’t symlinks anymore. rsync transferred the files referenced by these symlinks, not the symlinks themselves.

4.3. The -L Option

The -L option is useful for transferring all the symlinks as regular files. The symlinks aren’t created in this case:

$ rm –f destination_directory/*
$ rsync –L source_directory/* destination_directory/
$ ls -l destination_directory/
total 0
-rw-r--r-- 1 alice alice  6 May 12  8:35 file1
-rw-r--r-- 1 alice alice  6 May 12  8:35 flink1
-rw-r--r-- 1 alice alice  0 May 12  8:35 flink2
-rw-r--r-- 1 alice alice  6 May 12  8:35 flink3
-rw-r--r-- 1 alice alice  6 May 12  8:35 flink4

As it’s apparent from the output, all of the symlinks were copied as regular files.

We can also use the –copy-links option instead of -L, both of them are the same.

5. Conclusion

In this tutorial, we discussed several ways of copying symlinks using rsync. We saw that rsync ignores symlinks if we use it without any options.

The –l option lets us copy all of the symlinks.

If we want to ignore the symlinks pointing outside the destination directory and absolute symlinks, we can use the –safe-links option.

If we want to transfer the symlinks that point outside the source directory as regular files, we can use the –copy-unsafe-links option.

Finally, the -L option lets us transfer all of the symlinks as regular files.

Comments are closed on this article!