bashを使ってファイル名を整理したい。
例えばこんなファイルがあって
文字列「Perfume」で始まるファイルのうち、「Perfume」の後ろにアンダーバーが入っていないファイルだけを取り出して、そこに一括でアンダーバーを入れてやりたい。
ファイルの一括処理をするにはシェルでfor文を回せばいいだけ。ただ、処理するファイル名を捕まえる方法はbashのfor構文内では2箇所あるわけで、
つまり
$ for i in *ここ*; do echo "$i"; if [[ "$i" =~ "正規表現" ]]; then echo "$i"; 処理; fi; done
とすれば
ここの部分か、またはifの条件にある正規表現の箇所でファイルを捕まえられる。
ここの箇所の表現は(シェルがbashか、zshか、cshかによって)記法が変わってきちゃいそうなので、今回は(より柔軟そうな)ifの条件にある正規表現にて捕まえることにする。
$ for i in *Perfume*; do if [[ "$i" =~ .*Perfume[A-Z][a-z].* ]]; then echo "$i"; fi; done
あれ?2件しかひっかからない?あ、そうか。正規表現が間違っている。この正規表現だと「PerfumeDream」みたいに、大文字の次に小文字がくるやつしか引っかからないか。
長ったらしくなるが、if文の中に「or条件」で書いてみる。
$ for i in *Perfume*; do if [[ "$i" =~ .*Perfume[A-Z][a-z].* || "$i" =~ .*Perfume[A-Z][A-Z].* ]]; then echo "$i"; fi; done
今度はOK。ほしいファイル4件が引っ掛かった。
あとはmvにsedを使ってPerfumeのあとにアンダーバーを入れてやれば良い。
$ for i in *Perfume*; do if [[ "$i" =~ .*Perfume[A-Z][a-z].* || "$i" =~ .*Perfume[A-Z][A-Z].* ]]; then echo "$i"; \mv -f "$i" $(echo "$i" | sed -e s/"Perfume"/"Perfume_"/g); fi; done
lsで確認。
バッチリ変更された。
もしかして今回のはPOSIX表記だと(alnumとかで)もっとラクに書けたかもしれない。
BASH_REMATCH初めて知った
アンダーバーの後ろに日本語がくるファイル(レーザービームとか)もあるが、これを正規表現でひっかけるの癖がありそう。
と思ったらイッパツでできた。まじか。bash凄すぎるな。
$ for i in *Perfume*; do if [[ "$i" =~ .*Perfume[ぁ-ん] ]]; then echo "$i"; fi; done
次回はファイル文字列中に含まれる不要な英数字の連続部分だけを除去する。
これもfor文内部のif条件式の正規表現でファイルを捕まえてsedで処理させればいいだろうけど、sed内でも正規表現を使わないといけないから今回よりはちょっと難しいはず。次回試す。