我有一个Bash脚本,我在其中调用rsync
以执行到远程服务器的备份。要指定备份我的Downloads文件夹,我将"'${HOME}/Downloads'"
作为参数传递给rsync
,该参数会产生输出:
rsync -avu '/Volumes/Norman Data/Downloads' [email protected]:backup/
运行带有如上所述扩展的变量的命令(通过终端或在脚本中)可以很好地运行,但是由于扩展变量中的空间以及当包含在变量中时引号(单刻度)被忽略的事实,作为参数的一部分传递(请参见here),我唯一可以避免在空间上窒息的方法是:
stmt="rsync -avu '${HOME}/Downloads' [email protected]:backup/"
eval ${stmt}
[似乎在对脚本没有100%私有的任何内容上运行eval
会带来一些漏洞。我以为我应该以不同的方式这样做是否正确?如果是这样,那么对bash-script-beginner的任何提示将不胜感激。
** EDIT **-实际上,我涉及的用例要多一些。上面的例子。对于通过的路径,我有一个数组,每个数组包含空格,然后将它们组合成1个字符串,类似
include_paths=(
"'${HOME}/dir_a'"
"'${HOME}/dir_b' --exclude=video"
)
for item in "${include_paths[@]}"
do
inc_args="${inc_args}" ${item}
done
[inc_args
等于'/Volumes/Norman Data/me/dir_a' '/Volumes/Norman Data/me/dir_b' --exclude=video
然后我尝试将其作为参数传递给rsync
,但单跳号被当作文字读取,由于空格,它在第一个/Volumes/Norman
之后中断。
rsync -avu "${inc_args}" [email protected]:backup/
使用eval似乎以单引号作为引号并执行:
rsync -avu '/Volumes/Norman Data/me/dir_a' '/Volumes/Norman Data/me/dir_b' --exclude=video [email protected]:backup/
就像我需要它。我似乎无法找到其他工作方式。
对命令/选项使用数组,而不是普通变量。
stmt=(rsync -avu "'${HOME}/Dowloads'" [email protected]:backup/)
使用内置的command
执行]
command "${stmt[@]}"
...或者我个人只是将选项/参数放在一个数组中。
options=(-avu "'${HOME}/Download'" [email protected]:backup/)
使用
rsync
执行
rsync "${options[@]}"
如果您具有支持附加P.E.的较新版本的bash,参数扩展,那么您可能会引用该数组。
options=(-avu "${HOME}/Download" [email protected]:backup/)
通过应用P.E.检查输出
echo "${options[@]@Q}"
应打印
'-avu' '/Volumes/Norman Data/Downloads' '[email protected]:backup/'
那么你就可以
rsync "${options[@]@Q}"