如何正确地逃避 bash 脚本中使用的 rsync 排除模式?

如何正确地逃避 bash 脚本中使用的 rsync 排除模式?

脚本:

#!/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'"执行相同的操作,它就会起作用!未加引号的版本:

[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 扩展或解释特殊字符[

答案1

你应该读BashFAQ/050 又名我试图将命令放入变量中,但复杂的情况总是失败!

总结:

这会失败,因为 [...] 变量内的 [...] 引号是文字的,而不是句法的。

尝试将命令存储在变量中时,单词拆分也是一个问题。虽然您当前的示例没有这个问题,但必须注意这一点。

阅读完后,#050您可以重新评估是否真的需要这样做。如果您仍然认为需要这样做,并选择忽略反对的建议,则需要将命令存储在数组中:

cmd=( rsync -rlpuvz -e ssh "/www/${site}/" "${remote_host}:/www/${new_site}" --force --delete --exclude="site/web_sitemap_*.xml.gz" )
"${cmd[@]}"

相关内容