シェルスクリプトで空白をクォートしている引数とコマンドを変数に入れて実行する場合はevalを使う必要がある

何かタイトルが長くてわかりにくいですね。
普通に変数に入れているだけだと、クォートしていても空白区切りで別々の引数として認識される。

  • foo.sh

grep "foo bar"】を変数に入れて、それをそのまま実行する。

$ cat foo.sh 
#!/bin/bash
	
grep='grep "foo bar"'
	
echo $grep
$grep
$ ./foo.sh
grep "foo bar"
grep: bar": そのようなファイルやディレクトリはありません

変数をechoで出力している内容を見ている限り、問題なさそうだが。。。

  • bash -x でdebugしてみる

(sh -x だと同じようにgrep "foo bar" と見えるのでダメ)

$ bash -x foo.sh
+ grep='grep "foo bar"'
+ echo grep '"foo' 'bar"'
grep "foo bar"
+ grep '"foo' 'bar"'
grep: bar": そのようなファイルやディレクトリはありません

foo と bar が別々になってしまっている。


eval を使うと解決する。

$ cat foo.sh 
#!/bin/bash
grep='grep "foo bar"'
eval $grep