(可选)在bash脚本中传递参数

时间:2020-08-28 13:28:27

标签: bash rsync

我想在使用rsync时使用自定义身份文件,但前提是该文件存在,否则我不想为rsync麻烦使用custom ssh命令。我在报价方面遇到问题。查看示例。

所需的命令,如果存在身份文件

rsync -e "ssh -i '/tmp/id_rsa'" /tmp/dir/ u@h:/tmp/dir

所需的命令,如果身份文件不存在

rsync /tmp/dir/ u@h:/tmp/dir

我想创建一个包含-e "ssh -i '/tmp/id_rsa'"的变量,并按如下所述使用它

rsync ${identityArg} /tmp/dir/ u@h:/tmp/dir

此变量将为空或包含所需的ssh命令。

我填充变量的示例方法(我尝试了很多方法)

IDENTITY_FILE="/tmp/id_rsa"
if [ -f "${IDENTITY_FILE}" ]; then
  identityArg="-e 'ssh -i \"${IDENTITY_FILE}\"'"
fi

问题在于命令中的引号始终是错误的,而我最终得到的命令与此类似(在脚本中设置了set -x,这就是输出)

rsync -e '\ssh' -i '"/tmp/id_rsa"'\''' /tmp/dir/ u@h:/tmp/dir

我对bash的报价有些不了解。如果您对在bash脚本中使用单引号和双引号有任何好的资源,我想阅读它。

3 个答案:

答案 0 :(得分:2)

您要添加两个位置参数:-essh -i '/tmp/id_rsa',其中/tmp/id_rsa是扩展变量。您应该为此使用数组:

args=(/tmp/dir/ u@h:/tmp/dir)
idfile=/tmp/id_rsa

# Let [[ ... ]] do the quoting
if [[ -f $idfile ]]; then
    # Prepend two parameters to args array
    args=(-e "ssh -i '$idfile'" "${args[@]}")
fi

rsync "${args[@]}"

我不认为ssh -i的内部单引号是必需的,但这会扩展为问题中显示的命令。

答案 1 :(得分:0)

尝试这样

id=/tmp/id_rsa
[[ -e $id ]] && o1='-e' o2="ssh -i '$id'"
echo $o1 "$o2" /tmp/dir/ u@h:/tmp/dir

答案 2 :(得分:0)

尝试正确转义引号是棘手的。最好尝试利用现有构造。很少有其他选择,具体取决于情况

如果标识文件的名称仅包含简单字符(无空格,通配符等),请考虑不要将其用引号引起来。在这种情况下,您可以

IDENTITY_FILE="/tmp/id_rsa"
if [ -f "${IDENTITY_FILE}" ]; then
  identityArg="-e 'ssh -i ${IDENTITY_FILE}'"
fi
...
rsync $identityArg ...

另一种选择是始终传递命令(ssh或“ ssh -I ...”)。这将自动处理身份文件中的特殊字符。

IDENTITY_FILE="/tmp/id_rsa"
if [ -f "${IDENTITY_FILE}" ]; then
  identityArg="-i '${IDENTITY_FILE}'"
fi
rsync -e "ssh $identityArg" ...

第三种选择是使用数组创建rsync的参数,然后让shell根据需要对字符进行转义。这将允许身份文件中的任何字符。

IDENTITY_FILE="/tmp/id_rsa"
if [ -f "${IDENTITY_FILE}" ]; then
  identityArg=(-e "ssh -i '${IDENTITY_FILE}'")
fi
rsync "${identityArg[@]}" ...
相关问题