スペースを含むファイル名である可能性のあるオプションの引数を処理する方法

スペースを含むファイル名である可能性のあるオプションの引数を処理する方法

複数行のコマンド全体を省略します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[@]}"構文を使用して、二重性の別々の(スペースを含む)引数として配列の内容を提供できます。これにより、スペースやその他の珍しい文字を脱出することを考える必要がなくなります。

実際にDuplicityを呼び出さずにこれがどのように機能するかを確認するには、次のように引数を別の行に印刷する単純なスクリプトを使用できます。

#!/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

$STUFFとを考慮する必要があるため、二重性コマンドラインを設定するにはより多くの作業を実行する必要がありますが、追加の前後に$DESTINATIONargs配列に要素を追加してすべて同じ方法で処理できます。args+=("whatever")除外(適切な場合)もちろんです)。そして最後にduplicity "${args[@]}"

答え2

拡張は引用符の中にあるので、スペースはここで赤いニシンです。次のようにシェルからプログラムを呼び出すと:

program "$foo_path/$bar_name"

foo_path何でも含めるか何でも引数を受け取りますbar_name

それでは、見てみましょう。

--exclude "$2/${4:-__nosuchfiles__}" 

ここでは、空であるか存在しない場合は、パラメータのペア全体を削除して4解決策を見つけようとします。

${4:+--exclude} ${4:+"$2/$4"}

パラメータ:+置換演算子が必要です。 「空であるか設定されていない場合は何も変更しないでください。そうでない場合は代替を置き換えます。」これを--excludeパラメータに個別に適用します。

getopt実装(またはサポート自体をハッキング)するツールを使用すると、両方を--exclude=ARG使用できます--exclude ARGduplicityこれがうまくいけば、次のように利用できます。

${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>

関連情報