When using rsync over SSH, path escaping becomes particularly tricky because the command passes through multiple interpretation layers:
- Local shell expansion
- SSH command transmission
- 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)/"'
- Prefer
--protect-args
if using rsync 3.1.0+ - For older versions, use the double-quoting technique
- Test with
--dry-run
first when dealing with complex paths - 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:
- Local shell interpretation
- SSH command transmission
- 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