How to Force Rsync to Copy Broken Symlinks (Even When Referents Don’t Exist)


2 views

When working with rsync, you might encounter this frustrating warning:

symlink has no referent: "/a/path"

This occurs when rsync detects a symbolic link pointing to a non-existent location in the source filesystem. While this is technically correct behavior, there are valid use cases where you'd want to preserve these "broken" symlinks during transfer.

Rsync's default behavior is to skip symlinks when their targets don't exist. This becomes problematic when:

  • The target only exists in the destination environment
  • You're syncing development environments where paths differ
  • You need to maintain link structures regardless of target existence

The key option you need is:

rsync -a --copy-unsafe-links source/ destination/

This tells rsync to:

  1. Copy the symlink as-is
  2. Ignore whether the target exists
  3. Preserve all link attributes

For different scenarios, consider these variations:

# For absolute symlinks that should be made relative:
rsync -a --copy-unsafe-links --relative source/ destination/

# When you want to transform absolute to relative paths:
rsync -a --copy-unsafe-links --no-implied-dirs source/ destination/

Imagine syncing a web project where assets are symlinked:

# Source structure:
# /var/www/project/
#   ├── assets -> /mnt/storage/assets
#   └── index.html

# Destination needs same structure, but /mnt/storage isn't available yet
rsync -avz --copy-unsafe-links /var/www/project/ user@remote:/var/www/project/

This ensures the assets symlink is created on the remote server, even though /mnt/storage doesn't exist there yet.

  • Broken symlinks might cause issues in running systems
  • Consider using relative paths when possible
  • Test with --dry-run before actual transfer
  • Combine with --delete for exact mirroring

For complex scenarios, combine with other options:

# Preserve permissions and copy broken links:
rsync -a --copy-unsafe-links --perms --owner --group source/ destination/

# Exclude certain broken links while copying others:
rsync -a --copy-unsafe-links --exclude='*.tmp' source/ destination/

When using rsync to transfer files between systems, you might encounter this frustrating message:

symlink has no referent: "/a/path"

This occurs when rsync encounters a symbolic link pointing to a non-existent location in the source filesystem. While rsync considers this an error condition, there are valid use cases where you want to preserve these "broken" symlinks.

Several scenarios require copying broken symlinks:

  • When the target exists only in the destination environment
  • When maintaining relative path structures across systems
  • When the link destination will be created later in your deployment process

Rsync provides two key options for handling symlinks:

rsync -a --copy-unsafe-links source/ destination/

This tells rsync to copy the symlink as-is, regardless of whether its target exists. For more control, combine it with other options:

rsync -av --copy-unsafe-links --no-implied-dirs source/ remote:/path/

If you're dealing with absolute paths, this combination works well:

rsync -a --links --ignore-missing-args source/ destination/

The --links option preserves symlinks, while --ignore-missing-args prevents rsync from complaining about missing source files.

Consider this common web deployment scenario where you have:

app/
├── current -> releases/v1.2.3
├── releases/
│   └── v1.2.3/
└── shared/
    └── uploads/

The "current" symlink is initially broken until the release is deployed. Here's how to handle it:

rsync -az --copy-unsafe-links --delete \
    --exclude='releases/*' \
    --exclude='shared/*' \
    app/ user@production:/srv/app/

If you're still having issues:

  • Double-check your trailing slashes in paths
  • Test with --dry-run first
  • Combine with --verbose for more debugging info
  • Remember that relative symlinks behave differently than absolute ones