bashで半角スペースを含むファイル名を扱うには。

windows系のファイルは半角スペースが大好きだ。
ところがbashとは親和性がよくない。

そこでいくつか例題を書いておく。

実験ファイルの準備

$ :>"(a) [a] a.c";:>"(a) [b] a.c";:>"(a) [b] b.c";:>"(b) [a] a.c";:>"(a) [a] a.d";
$ ls
(a) [a] a.c  (a) [a] a.d  (a) [b] a.c  (a) [b] b.c  (b) [a] a.c

「:」コマンドはヌルファイルを作るときにtouchの代替として重宝する。

拡張子を.cから.eへ変換する

$ for i in *.c;do mv "$i" "${i//.c/.e}";done
$ ls
(a) [a] a.d  (a) [a] a.e  (a) [b] a.e  (a) [b] b.e  (b) [a] a.e

ポイントになるのは 変数i中に半角スペースが入っているため「"」でクオートしている点、ここで「'」では変換先である「${i//.c/.e}」もクオートされてしまうのでダブルクオートでないとだめ。

ファイル名の途中の文字[b]を[f]へ置換する

$ for i in *\[b\]*; do echo mv "$i" "${i//\[b\]/[f]}";done
mv (a) [b] a.e (a) [f] a.e
mv (a) [b] b.e (a) [f] b.e
$ for i in *\[b\]*; do mv "$i" "${i//\[b\]/[f]}";done
$ ls
(a) [a] a.d  (a) [a] a.e  (a) [f] a.e  (a) [f] b.e  (b) [a] a.e

まあほとんど同じなんだがポイントなのは、文字集合を表す[]をエスケープしている点。置換前だけでいい。
ここでやっているみたいに、実行前にechoをつけて確認しておくのが失敗しなくていい。

ファイル変換を大量に行う時にはこの辺のネタは重宝する。

変数を置換する${変数名//置換元文字列/置換先文字列}はすごく重宝するので覚えておいた方がいい。
ちなみに末尾を削除する%%は//で代替が効く。

$ i=aaaaabbbcc;echo ${i%%cc}
aaaaabbb
$ i=aaaaabbbcc;echo ${i//cc}
aaaaabbb