シェルスクリプトにおける空白の扱い

2026-04-29
Bash
Space
1
2
3
4
for file in * ;
do mv "${file}" "${file}_2";
done;

1
2
for file in `ls`  -> だめ
mv $file $file_2 -> 空白が入ると a a b とかになっておかしくなる
1
find . -type f | xargs -I % mv "%" "%"_2

そもそもなぜこれが問題になるのか?
Linuxにおいて、空白とはどのような意味合いを持つのか?

実際面の解決策は出ている。

では、この問題の背景は?なぜ問題になるのか?

IFS - Internal Field Separator

デフォルトは下記。

1
2
<space><tab><newline>
IFS=

こんな風にすると、IFSからSPACEがなくなるのでスペース区切りでファイル名が分割されずファイル名に空白を含んだファイルも上手に扱えるようになる。
でもー。このままじゃもとに戻せない。そこでIFS_BACKUP=$IFSとかやって取っておいて、シェルスクリプトの最後で元にもどしてやったりするとよい。

1
cat -etv <<<"$IFS"

bashにおいてIFSがファイル名の判断に使われていることは分かった。ではこれはいつどのように始まったものなのか?源流はどこなのだろうか?

IFSの源流は1979年にAT&TがリリースしたUNIX Version 7のBourne Shell(/bin/sh)にある。Steve Bourneが設計したもので、フィールド分割の区切り文字を固定値ではなく「設定可能」にすることで汎用性を持たせた。CSV処理やログ解析など、区切り文字が異なるデータを同じループ構文で扱えるという利点があった。

デフォルトがスペース・タブ・改行になっているのは、当時の用途に最適化された結果だ。人間がコマンドラインに打ち込む引数は空白区切りが自然であり、lsechoの出力も空白・改行区切りが標準だった。そして当時はファイル名にスペースを含める習慣がほぼ存在しなかったため、この設計は問題にならなかった。

問題が顕在化したのはGUIの普及によるものだ。macOSやWindowsを使うユーザーが “My Documents” のようなスペース入りファイル名を当たり前のように作るようになり、シェルスクリプトは想定外の入力を受け取るようになった。IFS自体は1979年時点では正しい設計だったが、世界が変わった。