bash変数にスペースを含む引用ファイル名を渡す

bash変数にスペースを含む引用ファイル名を渡す

Bashシェルでは、次の点を考慮してください。

$ x="-name 'foo bar'"
$ find $x
find: paths must precede expression: `bar''
$ find -name 'foo bar'
./foo bar

そのように動作さ$xせるには、何を入れることができますか?find $xfind -name 'foo bar'

答え1

単一の文字列に別の内容(-nameおよび)を入れないでください。foo bar

代わりに配列を使用してください。

args=( -name 'foo bar' )

find . "${args[@]}"

配列変数拡張の引用符は、各要素が個別に引用されることを保証します。これにより、これが単一のパラメータであることがfoo bar保証されます。

位置パラメータも使用できます。

set -- -name 'foo bar'

find . "$@"

繰り返しますが、引用は"$@"不可欠です。

-name 'foo bar'変数を入れて引用符なしで使用すると、findシェルは値をスペース、タブ、および改行で除算します。これはfind、ユーティリティがパラメータとを取得したこと-name'foo意味しますbar'bar'パラメータがわからないのでfind文句を言います。

文字列にワイルドカードパターン(たとえば)がある場合、-name '*.txt'シェルはそれを-name合計に分割'*.txt'し、'*.txt'現在のディレクトリで名前を拡張するためのワイルドカードパターンとして使用されます。

答え2

注:Linuxはfind構文をサポートしていますが、普遍的ではありません。たとえば、ほとんどのBSD派生では機能しませんが、次のような結果が得られます。

bash-3.2$ find -name 'foo bar'
find: illegal option -- n
usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
       find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]

問題は場所ではなく、引用と引用の解釈です。コードを次のように置き換えることができます。

x='foo bar'
find -name "$x"

あるいは、evalを試してみることもできます。

x="-name 'foo bar'"
eval "find $x"

少なくとも私のシステムでは、次のような結果が発生します。

bash-5.1$ x="-name 'foo bar'"
bash-5.1$ eval "find $x"
./foo bar

私はこれが望む結果だと信じています。

関連情報