我将省去您整个多行duplicity
命令,但我想知道是否有可能整理脚本中的一系列参数,如下所示:
--exclude "$2/${4:-__nosuchfiles__}" --exclude "$2/${5:-__nosuchfiles__}" ...
关键是$4
, $5
,... 是经常包含空格的名称。当前的公式是有效的,但代价是那些丑陋的默认设置,__nosuchfiles__
如果排除标准集小于通过的排除数,则不排除任何内容。这也是一种黑客行为,因为可以想象有人可能会创建一个名为 的文件夹__nosuchfiles__
,并且它可以处理的排除项数量有限制。
我想要的是定义
EXCLUDES='--exclude "Path 1" --exclude "Path 2"'
满足我需要的数量--exclude
,从无到大量,然后替换$EXCLUDES
为口是心非的命令行,例如:
duplicity $STUFF $EXCLUDES $SOURCE $DESTINATION
当然,当排除项指定包含空格的名称时,它不起作用,并且我无法制定出任何在脚本本身中定义和使用这样一组排除项的公式。 (如果任何答案也EXCLUDES=""
意味着完全不排除,则奖励积分。)
是的,我知道我可以使用 duplicity's --exclude-filelist
,但我想知道是否有一个通用的解决方案,不依赖于命令能够方便地从文件而不是从命令行读取名称列表。另请注意$2/
所有排除路径的前缀。
答案1
您需要使用数组而不是简单的字符串连接来构建口是心非的命令行。然后,您可以使用该"${array[@]}"
语法将数组的内容作为单独的(可能包含空格)参数提供给口是心非的。这使您不必考虑逃离空格或其他不寻常的字符。
要了解其工作原理而不实际调用口是心非,您可以使用一个简单的脚本,在单独的行上打印其参数,如下所示:
#!/bin/bash
printf "BEGIN\n"
for x in "$@"
do
printf "ARG: $x\n"
done
printf "END\n"
我已将其另存为args.sh
.
现在,我们需要使用数组构建一个命令,如下所示:
#!/bin/bash
if test -z "$1"
then
printf "Need at least one argument"
exit 1
fi
prefix=$1
shift
for arg in "$@"
do
args+=("--exclude")
args+=("$prefix/$arg")
done
./args.sh "${args[@]}"
实际上,其工作原理如下:
$ ./801811.sh foo bar "baz quux"
BEGIN
ARG: --exclude
ARG: foo/bar
ARG: --exclude
ARG: foo/baz quux
END
您需要做更多工作来设置 duplicity 命令行,因为您还需要考虑$STUFF
和$DESTINATION
,但这些都可以用相同的方式处理,方法是使用 向 args 数组添加元素args+=("whatever")
,可以在添加排除项之前或之后(视情况而定)。然后在最后,只需调用duplicity "${args[@]}"
。
答案2
空格在这里是一个转移注意力的东西,因为扩展是在引号内的。如果我们像这样从 shell 调用一个程序:
program "$foo_path/$bar_name"
它接收一个参数,无论什么foo_path
或bar_name
包含。
现在我们来看看:
--exclude "$2/${4:-__nosuchfiles__}"
在这里,您想要删除整个参数对(如果4
为空或不存在),从而产生解决方案:
${4:+--exclude} ${4:+"$2/$4"}
参数:+
替换运算符就是您所需要的:“如果这是空白或未设置,则不替换任何内容,否则替换替代项”。我们将其单独应用于--exclude
及其参数。
getopt
使用实现(或以其他方式破解支持本身)的工具可以--exclude=ARG
同时采用--exclude ARG
.如果duplicity
这样工作,我们就可以利用它:
${4:+"--exclude=$2/$4"}
完整的演示程序test.sh
:
#!/bin/bash
myargs()
{
for x in "$@" ; do printf "<%s>\n" "$x"; done
}
myargs ${1:+--foo-opt} ${1:+"x $1 x"}
运行:
$ ./test.sh
$ ./test.sh "" # blank treated like missing?
$ ./test.sh abc
<--foo-opt>
<x abc x>
$ ./test.sh "ab c"
<--foo-opt>
<x ab c x>