从外部 bash 文件传递​​变量未按预期运行

Passing variables from external bash file not behaving as expected

我有一个 bash 脚本,它使用 rsync 将一些文件从我的本地桌面备份到我 LAN 上的远程机器。

我在单独的 .sh 文件中有一些带有一些可自定义变量的主脚本,以便于维护、部署和 git 管理。

所以我有这个目录结构

sync-backup-to-cp.sh
config/settings.sh

并且以下代码将 config/settings.sh 包含到主 sync-backup-to-cp.sh

#! /bin/bash

#load variables file
source /Users/enwhat/Dropbox/Flex/Scripts/mac/rysnc-backup-to-cp/config/settings.sh

但是导入的变量没有按预期运行。如果我在任何变量中有任何 space 它会抛出有关变量无效的错误。 bash 似乎对此有奇怪的解释。

即。 rsync_opts="--verbose --archive" 将导致脚本中断和 运行 错误,例如“提供的数字参数无效或未知参数”。其中 rsync_opts="- -冗长”运行非常完美。

为了帮助说明脚本,我已经截取了一些代码片段以显示到目前为止的流程

来自:配置/settings.sh

RSYNC_OPTS=( --bwlimit=1000 --verbose ) 

在我的主脚本中,有一个函数调用,其中传递了这些变量。

backup "$RSYNC_BIN" "$BACKUP_FILE_LIST" "$EXCLUDE_FILE_LIST" "$SSH_PORT" "$SSH_KEY" "$SOURCE" "$DESTINATION" "$RSYNC_OPTS[*]"

那么完整的功能

function backup(){ #uses rsync to backup to server
    #takes 8 args 1

    #define local vars
    local l_rsync_bin=
    local l_rsync_backup_file_list=
    local l_rsync_exclude_file_list=
    local l_rsync_ssh_port=
    local l_rsync_ssh_key=
    local l_rsync_source=
    local l_rsync_dest=
    local l_rsync_opts=


    #local l_time
    #l_time=$(date)

    #caffinate stops system from sleeping
    echo ""$l_rsync_bin" "$l_rsync_opts" --verbose --archive --recursive --numeric-ids --human-readable --partial --progress --relative --itemize-changes --stats --rsync-path="sudo rsync" --delete-during --files-from="${l_rsync_backup_file_list}" --exclude-from="${l_rsync_exclude_file_list}" -e "ssh -q -p ${l_rsync_ssh_port} -i ${l_rsync_ssh_key}" "${l_rsync_source}" "${l_rsync_dest}""
    caffeinate -s "$l_rsync_bin" "$l_rsync_opts" --verbose --archive --recursive --numeric-ids --human-readable --partial --progress --relative --itemize-changes --stats --rsync-path="sudo rsync" --delete-during --files-from="${l_rsync_backup_file_list}" --exclude-from="${l_rsync_exclude_file_list}" -e "ssh -q -p ${l_rsync_ssh_port} -i ${l_rsync_ssh_key}" "${l_rsync_source}" "${l_rsync_dest}"

}

由于您引用 $rsync_opts,因此整个值作为单个 whitespace-containing 参数传递给 rsync。为了将每个选项作为单独的参数传递,您需要将参数扩展不加引号:

rsync $rsync_opts

但是,您不能像这样包含实际包含空格的参数; shell 将所有空格视为分隔参数。存储参数的正确方法是使用数组:

rsync_opts=( --verbose --archive )
rsync "${rsync_opts[@]}"

您当前的用例可能没有必要,但最好养成以正确方式做事的习惯,以避免以后出现令人讨厌的意外情况。

例如,

local -a l_rsync_opts
l_rsync_opts=(--bwlimit=1000 --verbose --rsync-path="sudo rsync")

更新:根据您的编辑,您需要执行以下操作:

backup ... "${RSYNC_OPTS[@]}"   # @, not *

# Note the changes involving l_rsync_opts
function backup(){ #uses rsync to backup to server
    #takes 8 args 1

    #define local vars
    local l_rsync_bin=
    local l_rsync_backup_file_list=
    local l_rsync_exclude_file_list=
    local l_rsync_ssh_port=
    local l_rsync_ssh_key=
    local l_rsync_source=
    local l_rsync_dest=
    local l_rsync_opts=( "${@:8}" )


    #local l_time
    #l_time=$(date)

    #caffinate stops system from sleeping
    echo ""$l_rsync_bin" "${l_rsync_opts[@]}" --verbose --archive --recursive --numeric-ids --human-readable --partial --progress --relative --itemize-changes --stats --rsync-path="sudo rsync" --delete-during --files-from="${l_rsync_backup_file_list}" --exclude-from="${l_rsync_exclude_file_list}" -e "ssh -q -p ${l_rsync_ssh_port} -i ${l_rsync_ssh_key}" "${l_rsync_source}" "${l_rsync_dest}""
    caffeinate -s "$l_rsync_bin" "${l_rsync_opts[@]}" --verbose --archive --recursive --numeric-ids --human-readable --partial --progress --relative --itemize-changes --stats --rsync-path="sudo rsync" --delete-during --files-from="${l_rsync_backup_file_list}" --exclude-from="${l_rsync_exclude_file_list}" -e "ssh -q -p ${l_rsync_ssh_port} -i ${l_rsync_ssh_key}" "${l_rsync_source}" "${l_rsync_dest}"

}