脚本:
#!/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
脚本输出:
[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
它似乎将引号视为“文字"文件名/模式字符。 "--exclude='site/web_sitemap_*.xml.gz'"单引号(未转义) "--exclude='site/web_sitemap_*.xml.gz'" 。 但是,如果我们尝试相同的东西,没有任何types的embedded式报价它的作品! 未加引号的版本:
[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
不使用引号似乎是答案,但是如果rsync排除模式包含通常由bash扩展或解释的符号(如:或;或\或[ )),如何防止shell扩展或特殊字符的解释?
你应该阅读BashFAQ / 050 aka我试图把一个命令在一个variables,但复杂的情况下总是失败! 。
A TL; DR:
这个失败是因为variables内部的引号是字面的; 不是语法的。
当尝试将命令存储在variables中时,分词也是一个问题。 虽然不是与你的直接例子,这是一个必须注意的事情。
一旦你阅读#050你可以重新评估,如果你真的需要这样做。 如果你仍然认为你做了,并select忽视对它的build议,你会想要将你的命令存储在一个数组中:
cmd=( rsync -rlpuvz -e ssh "/www/${site}/" "${remote_host}:/www/${new_site}" --force --delete --exclude="site/web_sitemap_*.xml.gz" ) "${cmd[@]}"