変数内のスペースを含む値を渡す

スペースを含む文字列を変数に格納してコマンドの引数として渡すときの動作を考える。

例えば以下のようにfiles変数にa.txtb.txtを格納してlsコマンドに渡すとする。

$ files="a.txt b.txt"
$ ls $files

シェルやシェルスクリプトでは変数は展開されて実行されるため、イメージとしては以下のようになる。

$ ls a.txt b.txt

ところがシェルによって動作が異なる。

bashの場合

bashでは展開された状態で動作する。

例えば上記lsコマンドの例では以下のように正常動作する。

[bash]
$ files="a.txt b.txt"
$ ls $files
a.txt  b.txt

上記ではlsコマンドにa.txtb.txtの2引数を渡した状態となるため、a.txtb.txtが存在する場合はそれぞれのファイルが表示される。

zshの場合

zshではスペースを含めた文字列を1つの引数として動作する。

[zsh]
$ files="a.txt b.txt"
$ ls $files
ls: cannot access 'a.txt b.txt': No such file or directory

上記例では"a.txt b.txt"という文字列をlsコマンドの1つの引数として渡しているため、a.txt b.txtというファイルが存在しないというエラーが表示される。

SH_WORD_SPLIT

zshbashと同じようにスペースを含む文字列を展開して複数の引数として扱いたい場合はSH_WORD_SPLITを設定する。

[zsh]
$ setopt SH_WORD_SPLIT
$ files="a.txt b.txt"
$ ls $files
a.txt  b.txt

上記例のようにSH_WORD_SPLITを設定すると、zshでもbashと同じようにスペースを含む文字列を展開して複数の引数として扱う。

SH_WORD_SPLITの解除

SH_WORD_SPLITを解除するにはunsetoptコマンドを実行する。

$ unsetopt SH_WORD_SPLIT

ダブルクオートで囲った場合

setopt SH_WORD_SPLITを設定している場合でもダブルクオートで囲むと1つの引数として扱われる。

$ setopt SH_WORD_SPLIT
$ files="a.txt b.txt"
$ ls "$files"
ls: cannot access 'a.txt b.txt': No such file or directory