私は次の2つのコマンドを実行しています。
echo $(find ./ $OPT1 $OPT2 $OPT3)
echo find ./ $OPT1 $OPT2 $OPT3 | bash
奇妙なことに、topコマンドは結果を出ませんが、lowerコマンドは結果を返します。なぜそんなことですか?
答え1
最初はfind ./ $OPT1 $OPT2 $OPT3
トークン化を実行し、グローバル(引用符なし)を出力し、それを印刷する$()
ために渡します。echo
これはデフォルトでコマンドを実行するのと同じですfind
が、改行文字は空白になり、ファイル名が含まれるかfind
印刷されると拡張されます。しかし、コンテンツに異常なコンテンツが含まれている場合は、単語の分割も同様に奇妙です。 (他のものは参照されていないため、に渡される前に分割され、ワイルドカードされます。)*
?
IFS
$OPT1
find
2番目は、を印刷してfind ./ $OPT1 $OPT2 $OPT3
変数を展開し(引用符がないので再分割してワイルドカードを使用)、結果をbash
コマンドとして実行するために渡します。 running とほぼ同じですfind
が、変数にシェルメタ文字が含まれている場合は、2番目のシェルによって(再び)拡張されます。
まず、ファイル名がfoo*
拡張され、3つすべてがワイルドカードとして表示されます。
$ touch foo1 foo2 foo\*
$ echo $(find .)
. ./foo2 ./foo* ./foo1 ./foo2 ./foo1
第二に、bashのパイピングのために使用したものなどの内部変数が拡張されることに注意してくださいeval
。
$ OPT='echo $BASH_VERSION'
$ echo $OPT
echo $BASH_VERSION
$ echo $OPT | bash
4.3.30(1)-release
$ eval $OPT # about the same
4.3.30(1)-release
BASH_VERSION
変数の拡張はおそらく最も簡単な例です。ただし、以下に示すように、いずれの場合もエクスポートした変数やシェル内の他の変数が必要です。 (find
今では合理的な例は思い出せません。)
変数に含まれる内容によっては、追加の評価ラウンドで一致するかどうかがOPT
異なります。find