eval は悪だと誰もが言うので、代わりに $() を使用する必要があります。しかし、引用符の解除が $() 内で同じように処理されない状況に遭遇しました。
背景として、私はスペースを含むファイル パスに頻繁に悩まされてきたので、そのようなパスをすべて引用したいと思います。私のすべての実行可能ファイルがどこから来ているのか知りたいというより多くのパラノイア。さらに偏執的で、自分自身を信頼していないので、これから実行しようとしている作成済みのコマンドを表示できるようになります。
以下では、eval と $() の使用のバリエーションと、コマンド名が引用符で囲まれているかどうか (スペースが含まれている可能性があるため) を試します。
BIN_LS="/bin/ls"
thefile="arf"
thecmd="\"${BIN_LS}\" -ld -- \"${thefile}\""
echo -e "\n Running command '${thecmd}'"
$($thecmd)
Running command '"/bin/ls" -ld -- "arf"'
./foo.sh: line 8: "/bin/ls": No such file or directory
echo -e "\n Eval'ing command '${thecmd}'"
eval $thecmd
Eval'ing command '"/bin/ls" -ld -- "arf"'
/bin/ls: cannot access arf: No such file or directory
thecmd="${BIN_LS} -ld -- \"${thefile}\""
echo -e "\n Running command '${thecmd}'"
$($thecmd)
Running command '/bin/ls -ld -- "arf"'
/bin/ls: cannot access "arf": No such file or directory
echo -e "\n Eval'ing command '${thecmd}'"
eval $thecmd
Eval'ing command '/bin/ls -ld -- "arf"'
/bin/ls: cannot access arf: No such file or directory
$("/bin/ls" -ld -- "${thefile}")
/bin/ls: cannot access arf: No such file or directory
だから...これは紛らわしいです。引用符で囲まれたコマンド パスは、$() コンストラクト内を除いてどこでも有効ですか? より短く、より直接的な例:
$ c="\"/bin/ls\" arf"
$ $($c)
-bash: "/bin/ls": No such file or directory
$ eval $c
/bin/ls: cannot access arf: No such file or directory
$ $("/bin/ls" arf)
/bin/ls: cannot access arf: No such file or directory
$ "/bin/ls" arf
/bin/ls: cannot access arf: No such file or directory
$($c)
単純なケースをどのように説明し ますか?