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" ''

このエラーを回避する1つの方法は、$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 ...

よりスマートなアイデアを持つ人がいますか?

答え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

関連情報