Skip to content

rcシェルで空白が含まれるファイル名を正しく扱う

This content is a draft and will not be included in production builds.

Plan 9の rc(1) シェルでは、グロブでファイル名のマッチングを行った場合に正しくスペースを扱える。例えば

Terminal window
% ls
a
'b c'

のようにファイルが存在するディレクトリで、

for(i in *)
echo $i

を実行すると ab c の2行が出力される。同様に代入でも同じルールで展開される。

Terminal window
% a=*c
% whatis a
a='b c'

Plan 9のコマンドは、ファイル名にスペースが含まれる場合にクオートで括って出力する習慣がある1ls(1) の例は上で挙げたが、他にも getflagsventi あたりもこの習慣に従っている。

しかしコマンド出力を ifs で分割する際にはクオートを考慮しない。なので

x=`{ls}
whatis x

を実行すると x

  • a
  • ‘b
  • c’

という要素を3つ持ったリストに分割されてしまって、おそらく意図した結果にならない。なので ls の場合は -Q オプションでクオートを無効化する。

nl='
'
x=`$n{ls -Q}
# 古い場合はこちら
ifs=$n {x=`{9 ls -Q}}

ただし改行文字が正しいファイル名に含まれてしまっている場合は別の対策が必要になる。また、read で1行ずつ読む場合の対策はおそらく無い。

  1. awkなど古くからあるコマンドでは対応していない場合もある