Sunday, January 22, 2006

Odd behavior of rsync on Mac OS X

Today, I was trying to type an rsync command that would copy all my iPhotos from one computer to another. Since the final directory in the path contains a space character ("iPhoto Library"), I included it in single quotes, like this (username and computer are not the actual values I used :-)

rsync -avz username@computer.local:/Users/Shared/Pictures/'iPhoto Library/' /Users/Shared/Pictures/'iPhoto Library/'

After pressing Enter and entering my password, rsync gave the error:

receiving file list ... rsync: link_stat "/Users/Shared/Pictures/iPhoto" failed: No such file or directory (2)

Clearly, the single quotes weren't doing the job. So I replaced single with double-quotes. Still no luck. After googling space chars in directory names, and learning about the backslash, I tried 'iPhoto\ Library/'. This kinda worked: Rsync found the right source directory, but on the destination machine it created a directory named iPhoto\ Library. But at least the results suggested a solution. I changed the destination directory to 'iPhoto Library/', so the entire command looked assymetrically like this:

rsync -avz username@computer.local:/Users/Shared/Pictures/'iPhoto\ Library/' /Users/Shared/Pictures/'iPhoto Library/'

Eureka! It works. My only problem is I don't know why the specification of the source directory needs both single-quotes and a backslash to represent a space character, but the destination directory needs only single-quotes and a space?

-Xot

1 comment:

Michael said...

you are a victim of the way unix hadles command line expansion

if you type "programname *" to the shell, the "*" is expanded before "progname" is even run. this was a feature of unix, that all programs inherit the power of the shell without having to know anything about it.

so what happened to your original command is this:

rsync on the local machine is executed with two areguments:

Argument #1: username@computer.local:/Users/Shared/Pictures/iPhoto Library/
Argument #2: /Users/Shared/Pictures/iPhoto Library/

All of your quotes are stripped away, and the spaces are properly embedded in the arguments ... looking good

but ... rsync in the remote site probably passes its argument to a shell for expansion, which means that on the remote side that space is going to be interpreted as a space between file names. In order for this to work you will need to quote the space for the remote filename twice, once for the shell running on the local system, and once for the shell on the remote system.