Script:
#!/bin/bash
site=$1
remote_host=$2
new_site=${3:-$1}
cmd="rsync -rlpuvz -e ssh /www/$site/ $remote_host:/www/$new_site --force --delete --exclude=\"site/web_sitemap_*.xml.gz\""
echo $cmd
$cmd
Script output:
[xxx@xxx ~]$ rsync -rlpuvz -e ssh /www/xxx/ xxx:/www/xxx --force --delete --exclude="site/web_sitemap_*.xml.gz"
sending incremental file list
deleting site/web_sitemap_ff3abe06_000.xml.gz
It seems to be treating the quotes \"
as literal "
filename/pattern characters. I get the same thing with single-quotes (unescaped) '
as in "--exclude='site/web_sitemap_*.xml.gz'"
. HOWEVER, If we try the same thing without any type of embedded quotes it works! Unquoted version:
[xxx@xxx ~]$ touch /www/xxx/site/web_sitemap_ff3abe06_000.xml.gz
[xxx@xxx ~]$ rsync -rlpuvz -e ssh /www/xxx/ xxx:/www/xxx --force --delete --exclude=site/web_sitemap_*.xml.gz
sending incremental file list
sent 41624 bytes received 290 bytes 7620.73 bytes/sec
total size is 18233892 speedup is 435.03
Not using quotes seems like the answer but then how do I protect against shell expansion or interpretation of special characters in cases were the rsync exclude pattern contains symbols that would normally be expanded or interpreted by bash (like :
or ;
or \
or [
) ?
Best Answer
You should read BashFAQ/050 aka I'm trying to put a command in a variable, but the complex cases always fail!.
A TL;DR:
Word splitting is also a problem when trying to store a command in a variable. Although not with your immediate example this is something one has to be aware of.
Once you have read
#050
you can re-evaluate if you really need to do this. If you still think you do and choose to disregard the advice against it you will want to store your command in an array: