Properly Escaping Spaces in Remote Paths for rsync over SSH: A Technical Deep Dive


2 views

When using rsync over SSH, path escaping becomes particularly tricky because the command passes through multiple interpretation layers:

  1. Local shell expansion
  2. SSH command transmission
  3. Remote shell interpretation

Here are the methods we've examined and why they fail:

# Failed attempt 1 - Simple backslash escaping
rsync -avz /local/path/with\\ space/ user@host:/remote/path/with\\ space/

# Result: Remote interprets as "/remote/path/with/" only
# Failed attempt 2 - Triple escaping
rsync -avz /local/path/with\\\\\\ space/ user@host:/remote/path/with\\\\\\ space/

# Result: Remote sees "/remote/path/with\/" - still incomplete
# Failed attempt 3 - Quoting
rsync -avz "/local/path/with space/" "user@host:/remote/path/with space/"

# Result: Similar truncation occurs

The reliable method combines shell quoting with rsync's own escaping:

# Correct approach for spaces
rsync -avz "/local/path/with space/" user@host:'"/remote/path/with space/"'

# For paths containing hyphens
rsync -avz "/local/path/with - hyphen/" user@host:'"/remote/path/with - hyphen/"'

The magic happens through:

  • Outer single quotes protect the entire remote path specification
  • Inner double quotes preserve spaces for the remote shell
  • The combination ensures proper transmission through SSH

Modern rsync versions (3.1.0+) offer a cleaner solution:

rsync -avz --protect-args "/local/path/with space/" user@host:/remote/path/with space/

# This tells rsync to handle all argument processing itself

For particularly problematic paths containing multiple special characters:

# Path with spaces and hyphens
rsync -avz --protect-args "/local/weird - path/name (v2)/" \
user@host:'"/remote/weird - path/name (v2)/"'
  1. Prefer --protect-args if using rsync 3.1.0+
  2. For older versions, use the double-quoting technique
  3. Test with --dry-run first when dealing with complex paths
  4. Consider temporarily renaming problematic directories as a last resort

When working with rsync over SSH, spaces in remote paths present a unique challenge because the escaping mechanism needs to work through multiple layers of interpretation:

  1. Local shell interpretation
  2. SSH command transmission
  3. Remote shell interpretation

The naive approach of using backslashes fails because:

rsync -avz /local/path/with\\ space/ user@host:/remote/path/with\\ space/

This gets interpreted as two separate paths on the remote server: /remote/path/with/ and space/

Method 1: Triple Escaping

For paths with simple spaces:

rsync -avz /local/path/with\\\\\\ space/ user@host:/remote/path/with\\\\\\ space/

The triple backslash becomes a single backslash on the remote side.

Method 2: Using Single Quotes

For more complex paths (recommended approach):

rsync -avz '/local/path/with space/' 'user@host:/remote/path/with space/'

Method 3: SSH Command Mode

For paths containing special characters like hyphens:

rsync -avz /local/path/ user@host:'"/remote/path/with space - special/"'

For paths containing both spaces and hyphens:

rsync -avz -- '/local/path/with special - chars/' 'user@host:/remote/path/with special - chars/'

The -- option tells rsync to stop processing command-line options.

When dealing with extremely complex paths:

ssh user@host 'mkdir -p "/tmp/rsync_temp"'
rsync -avz /local/path/ user@host:/tmp/rsync_temp/
ssh user@host 'mv /tmp/rsync_temp/* "/destination/with complex path/"'
  • Always test with --dry-run first
  • Consider using relative paths when possible
  • For production scripts, use variables to store complex paths