Shell脚本:使用内部选项创建变量


11

我有一个带有以下参数的rsync命令:

rsync -avz --{partial,stats,delete,exclude=".*"}

我想将该参数放在变量中以在脚本中重用。像这样:

#!/bin/bash
VAR=rsync -avz --{partial,stats,delete,exclude=".*"}
$VAR /dir1 /dir2

我尝试使用引号,单引号,方括号,但未成功。



之前已经走过这条路线:确保最终生成的命令字符串中没有空字符串。如果确实如此,则rsync可能会将它们用作参数,并且由于它们是不可见的,因此很难调试。我有一个空的第一个参数,rsync将其解释为在要复制的事物源中包括当前目录。

Answers:


12

从不建议将复杂的命令放在变量中。参见BashFAQ / 050-我试图将命令放入变量中,但是复杂的情况总是会失败!

如果您只是决定使用函数而不是变量并将参数传递给它,则您的要求将变得非常简单。

就像是

rsync_custom() {
    [ "$#" -eq 0 ] && { printf 'no arguments supplied' >&2; exit 1 ; }
    rsync -avz --{partial,stats,delete,exclude=".*"} "$@"
}

现在将所需的参数传递给它

rsync_custom /dir1 /dir2

函数定义在某种程度上很简单,我们首先使用$#不应该为零的变量来检查输入参数计数。我们抛出一条错误消息,提示未提供任何参数。如果存在有效的参数,则"$@"表示提供给函数的实际参数。

如果这是一个函数,那么您将经常使用该函数.bashrc.bash_profile例如,也在脚本/命令行中,将其添加到shell启动文件中。

或者如前所述,可能值得将大括号扩展名扩展为单独的arg,以提高可读性,因为

rsync_custom() {
    [ "$#" -eq 0 ] && { printf 'no arguments supplied' >&2; exit 1 ; }
    rsync -avz --partial --stats --delete --exclude=".*" "$@"
}

5
VAR=rsync -avz --{partial,stats,delete,exclude=".*"}

这种尝试运行命令-avz与参数--partial--stats等等。并与VAR设置为rsync在环境中。

VAR='rsync -avz --{partial,stats,delete,exclude=".*"}'

带引号的形式不起作用,因为括号没有用引号引起来,也没有在内部赋值,并且在变量扩展后也没有被引起来。

如果需要将命令行参数存储在变量中,请使用数组:

args=(rsync -avz --{partial,stats,delete,exclude=".*"})

现在"${args[@]}"将扩大到rsync-avz--partial,等作为不同的词。

数组还允许您根据需要有条件地将选项追加到列表,因此您可以例如:

args=(this that)
if something ; then
    args+=(another_arg)
fi
"$cmd" "${args[@]}"

1

您可以至少将选项部分保存在变量中:

opts=$(echo --{ignore-case,word-regexp,count,exclude='"sys*.*"'})

测试很重要,因为屏蔽可能很困难:

echo $opts
--ignore-case --word-regexp --count --exclude="sys*"

grep $opts bytes *.log 

由于存在多种选择,例如使用历史记录,使用别名,使用函数,因此我无法想到明显的用例。很少有在不同程序之间共享的复杂选项,因此对于交互式shell的临时解决方案,别名似乎是一种更好的方法:

alias cgrep='grep --ignore-case --word-regexp --count --exclude="sys*"'
cgrep bytes *.log

您的样品

VAR=rsync -avz --{partial,stats,delete,exclude=".*"}

无法使用,因为赋值是第一个空白处的尾码。您必须掩盖空白:

VAR='rsync -avz --{partial,stats,delete,exclude=".*"}'

使用--delete选项进行测试非常危险,不是吗?由于选项可以再次包含“,”和单引号,因此屏蔽很快就会变得困难。我会去别名或依靠历史。

别名可以存储在〜/ .bashrc文件中,以便在多个会话中连续使用。函数也可以存储在bashrc中,但如果要处理参数,则只需要将它们传递到要在其中进行评估的函数中即可。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.