Bash:带有可选参数的命令行

Bash:带有可选参数的命令行

我正在运行这种代码:

#!/usr/bin/env bash
set -u
exclude1='--exclude=/path/*'
exclude2='--exclude=/path with spaces/*'
exclude3=''        # any 'exclude' can be empty
tar -czf backup.tgz "$exclude1" "$exclude2" "$exclude3" 2>&1 | grep -i 'my_reg_exp' > error.log
RESULT=("${PIPESTATUS[@]}")
... etc ...

当我运行此代码时,我收到此错误:

tar: : Cannot stat: No such file or directory

这是因为“$exclude3”被翻译为空参数。就像我这样做一样:

tar -czf backup.tgz "$exclude1" "$exclude2" ''

避免此错误的一种方法是删除 $excludeX 周围的双引号。但如果 $excludeX 包含任何空格或其他奇怪的字符,这就会出现问题。

另一种方法是使用evalbut 因为我需要保留双引号,所以我不知道如何在需要时抑制引号和空参数。

我找到的唯一解决方案是使用字符串连接构造命令行:

CMD='tar -czf backup.tgz'
if [[ -n "$exclude1" ]]; then CMD+=" \"$exclude1\" "; fi
if [[ -n "$exclude2" ]]; then CMD+=" \"$exclude2\" "; fi
if [[ -n "$exclude3" ]]; then CMD+=" \"$exclude3\" "; fi
eval $CMD 2>&1 | grep -i 'my_reg_exp' > error.log
RESULT=("${PIPESTATUS[@]}")
... etc ...

有人有更聪明的主意吗?

答案1

tar -czf backup.tgz "$exclude1" "$exclude2" ${exclude3+"$exclude3"} 2>&1

${exclude3+"$exclude3"}如果$exclude3未设置,则展开为空"$exclude3";如果设置,则展开为 。

(对于其他可能未设置的变量也类似。)

请注意,未设置的变量和设置为空字符串的变量之间存在差异,因此您应该使用

unset exclude3

代替

exclude3=''

答案2

由于您在 bash 中工作,因此请使用大批

excludes=()
excludes+=('--exclude=/path/*')
tar -czf backup.tgz "${excludes[@]}"

如果某个变量中有可选条目,请将其添加到条件中。

if [[ -n $exclude_or_empty ]]; then excludes+=("$exclude_or_empty"); fi

答案3

这在 Ubuntu 上的 bash 中适用于我,但我不知道它是否符合 POSIX 标准/兼容:

tar -czf backup.tgz \
$(if "$exclude1" != ""); then echo "$exclude1"; fi
$(if "$exclude2" != ""); then echo "$exclude3"; fi
$(if "$exclude3" != ""); then echo "$exclude3"; fi

相关内容