How to escape spaces in rsync source and destination paths
Carney Mimms
carney.mimms at nourison.com
Fri Aug 22 18:56:44 GMT 2008
Matt,
Thank you for your suggestion, and rewrite. Bash arrays seem like a much
better approach and once I got the syntax straight, let the script run
without tripping over the whitespace.
I still need some help, though, as the script now runs without actually
doing anything or producing any feedback. When I removed the --dry-run flag
and added the --vv flag it now runs without error, but doesn't actually copy
anything. I added some test files to the source to be sure. I have also set
the --progress flag. As you can see the bash command echoes back properly,
it just doesn't actually do anything.
Am I missing something? Is there anything I can do to at least get the
script to produce some feedback?
Many thanks,
--Carneyh
-------------------------------------------------------------
#!/bin/bash
# Space-separated list of directories to back up; edit as needed; SOURCE
#DIRS variable now uses arrays instead of escaping spaces
DIRS=("admin at 192.168.100.47:/Volumes/Christine/Complete Rug Archive/Layered
Rooms/")
# Options to pass to rsync; edit as needed
# "--update" = update only (don't overwrite newer versions of files)
# "--delete"= delete files that exist on DESTINATION BUT NOT SOURCE"
# "--protect-args"= don't parse all spaces as separators
# "--dry-run"= run script without actually performing file operations-test
OPTS=(-aAX --vv --progress --delete --archive
--rsync-path=/usr/local/bin/rsync --protect-args)
# Backup destination. In this case, it is another hard disk on the same
machine.
# Incidentally, it is DOS-formatted, irrelevant here.
# If you wish to back up to a server via ssh, change the line to something
like
#
BACKUPDIR="remoteusername at someserver.something:/path/to/backup/destination"
# BACKUPDIR in this script is on local machine
BACKUPDIR="/Volumes/Paris/Complete Rug Archive/Layered Rooms/"
# ignore Mac droppings
EXCLUDES=(--exclude .DS_Store --exclude .Trash --exclude Cache --exclude
Caches)
# Build the actual command
# NOTE the specific path to the "special" version of rsync
# uses arrays instead of escaping spaces
COMMAND=(/usr/local/bin/rsync "${OPTS[@]}" "${EXCLUDES[@]}" "${DIRS[@]}"
"$BACKUPDIR")
# Informative output
echo About to run:
echo "${COMMAND[*]}"
echo Please do not close this window until it is finished.
# DO IT!
----------------
xserve03:/Users/admin/Documents/Rsync 3.0.3/rsync_scripts root#
./rsync_script_1.5.sh
About to run:
/usr/local/bin/rsync -aAX --vv --progress --delete --archive
--rsync-path=/usr/local/bin/rsync --protect-args --exclude .DS_Store
--exclude .Trash --exclude Cache --exclude Caches
admin at 192.168.100.47:/Volumes/Christine/Complete Rug Archive/Layered Rooms/
/Volumes/Paris/Complete Rug Archive/Layered Rooms/
Please do not close this window until it is finished.
Done.
xserve03:/Users/admin/Documents/Rsync 3.0.3/rsync_scripts root#
---------------------------------
On 8/21/08 9:32 PM, "Matt McCutchen" <matt at mattmccutchen.net> wrote:
> On Thu, 2008-08-21 at 16:32 -0400, Carney Mimms wrote:
>> Thank you for taking an interest in my problem of escaping spaces.
>> Here is the entire script and the entire output. I am at my wits end
>> as I have tried every every trick I know or have heard of, including \
>> \\ and adding single quotes. I added protect-args at your suggestion,
>> but it doesn¹t seem to change anything. I am running the script as
>> root for now to take sudo out of the picture. I have also tried
>> putting the paths directly in the command as arguments, rather than as
>> script variables.
>
>> #!/bin/bash
>>
>> # Space-separated list of directories to back up; edit as needed;
>> SOURCE
>> #DIRS="/Volumes/Christine/Complete\ Rug\ Image\ Archive/Misc"
>> DIRS="admin at 192.168.100.47:/Volumes/Christine/Complete\ Rug\ Image\
>> Archive/Layered\ Rooms/"
>> # Options to pass to rsync; edit as needed
>> # "--update" = update only (don't overwrite newer versions of files)
>> # "--delete"= delete files that exist on DESTINATION BUT NOT SOURCE"
>> OPTS="-avAX --progress --delete --rsync-path=/usr/local/bin/rsync
>> --protect-args --dry-run"
>>
>> # If you wish to back up to a server via ssh, change the line to
>> something like
>> #
>> BACKUPDIR="remoteusername at someserver.something:/path/to/backup/destination"
>> #BACKUPDIR="admin at 192.168.110.46:/Volumes/Paris/Complete Rug Image
>> Archive/Misc/"
>> BACKUPDIR="/Volumes/Paris/Complete\ Rug\ Image\ Archive/Layered\
>> Rooms/"
>> # ignore Mac droppings
>> EXCLUDES="--exclude .DS_Store --exclude .Trash --exclude Cache
>> --exclude Caches"
>>
>> # Build the actual command
>> # NOTE the specific path to the "special" version of rsync
>> COMMAND="/usr/local/bin/rsync $OPTS $EXCLUDES $DIRS $BACKUPDIR"
>>
>> # Informative output
>> echo About to run:
>> echo $COMMAND
>> echo Please do not close this window until it is finished.
>>
>> # DO IT!
>> $COMMAND
>>
>> echo Done.
>>
>> # the end.
>
> Here's your problem: when you expand a variable outside of quotes (in
> this case $COMMAND), bash word-splits on whitespace in $COMMAND but does
> not recognize any form of quoting or escaping within $COMMAND. Thus,
> there is nothing you can put in $COMMAND that will generate an argument
> containing a space. This came up before:
>
> http://lists.samba.org/archive/rsync/2008-April/020620.html
>
> In this situation, I recommend using bash arrays, which let you store,
> manipulate, and finally execute lists of arguments without the local
> shell mangling spaces in the arguments. Since you're using
> --protect-args, rsync won't let the remote shell mangle the spaces
> either, so all you have to do is quote the spaces when they are
> originally inserted into an array. Here's your script rewritten to use
> arrays (lightly tested):
>
> -----
> #!/bin/bash
>
> # Space-separated list of directories to back up; edit as needed; SOURCE
> #DIRS=("admin at 192.168.100.47:/Volumes/Christine/Complete Rug Image
> Archive/Misc" "admin at 192.168.100.47:/Volumes/Christine/Other Source")
> DIRS=("admin at 192.168.100.47:/Volumes/Christine/Complete Rug Image
> Archive/Layered Rooms/")
> # Options to pass to rsync; edit as needed
> # "--update" = update only (don't overwrite newer versions of files)
> # "--delete"= delete files that exist on DESTINATION BUT NOT SOURCE"
> OPTS=(-avAX --progress --delete --rsync-path=/usr/local/bin/rsync
> --protect-args --dry-run)
>
> # If you wish to back up to a server via ssh, change the line to something
> like
> # BACKUPDIR="remoteusername at someserver.something:/path/to/backup/destination"
> #BACKUPDIR="admin at 192.168.110.46:/Volumes/Paris/Complete Rug Image
> Archive/Misc/"
> BACKUPDIR="/Volumes/Paris/Complete Rug Image Archive/Layered Rooms/"
> # ignore Mac droppings
> EXCLUDES=(--exclude .DS_Store --exclude .Trash --exclude Cache --exclude
> Caches)
>
> # Build the actual command
> # NOTE the specific path to the "special" version of rsync
> COMMAND=(/usr/local/bin/rsync "${OPTS[@]}" "${EXCLUDES[@]}" "${DIRS[@]}"
> "$BACKUPDIR")
>
> # Informative output
> echo About to run:
> echo "${COMMAND[*]}"
> echo Please do not close this window until it is finished.
>
> # DO IT!
> : "${COMMAND[@]}"
>
> echo Done.
>
> # the end.
> -----
>
> Matt
More information about the rsync
mailing list