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

Gre*_*SAT 7 bash quoting arguments

我正在运行这种代码:

#!/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 ...
Run Code Online (Sandbox Code Playgroud)

当我运行此代码时,出现此错误:

tar: : Cannot stat: No such file or directory
Run Code Online (Sandbox Code Playgroud)

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

tar -czf backup.tgz "$exclude1" "$exclude2" ''
Run Code Online (Sandbox Code Playgroud)

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

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

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

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 ...
Run Code Online (Sandbox Code Playgroud)

有人有更聪明的主意吗?

Uwe*_*Uwe 7

tar -czf backup.tgz "$exclude1" "$exclude2" ${exclude3+"$exclude3"} 2>&1
Run Code Online (Sandbox Code Playgroud)

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

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

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

unset exclude3
Run Code Online (Sandbox Code Playgroud)

代替

exclude3=''
Run Code Online (Sandbox Code Playgroud)


Gil*_*il' 7

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

excludes=()
excludes+=('--exclude=/path/*')
…
tar -czf backup.tgz "${excludes[@]}"
Run Code Online (Sandbox Code Playgroud)

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

if [[ -n $exclude_or_empty ]]; then excludes+=("$exclude_or_empty"); fi
Run Code Online (Sandbox Code Playgroud)