min117の日記

初期desireもち。趣味Mac,メインFedora,仕事xp。

bash シェルで正規表現を駆使してファイル名を一括変更する

bashを使ってファイル名を整理したい。

f:id:min117:20191026214556p:plain


例えばこんなファイルがあって

f:id:min117:20191026213846p:plain

文字列「Perfume」で始まるファイルのうち、「Perfume」の後ろにアンダーバーが入っていないファイルだけを取り出して、そこに一括でアンダーバーを入れてやりたい。

 

ファイルの一括処理をするにはシェルでfor文を回せばいいだけ。ただ、処理するファイル名を捕まえる方法はbashのfor構文内では2箇所あるわけで、

つまり

$ for i in *ここ*; do echo "$i"; if [[ "$i" =~ "正規表現" ]]; then echo "$i"; 処理; fi; done

f:id:min117:20191026210401p:plain

とすれば

ここの部分か、またはifの条件にある正規表現の箇所でファイルを捕まえられる。

 

ここの箇所の表現は(シェルがbashか、zshか、cshかによって)記法が変わってきちゃいそうなので、今回は(より柔軟そうな)ifの条件にある正規表現にて捕まえることにする。

 

 

 

$ for i in *Perfume*; do if [[ "$i" =~ .*Perfume[A-Z][a-z].* ]]; then echo "$i"; fi; done

f:id:min117:20191026213009p:plain

あれ?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

f:id:min117:20191026213105p:plain

今度は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 

f:id:min117:20191026213753p:plain

 

lsで確認。

f:id:min117:20191026214200p:plain

バッチリ変更された。

 

もしかして今回のはPOSIX表記だと(alnumとかで)もっとラクに書けたかもしれない。

www.koikikukan.com

f:id:min117:20191026215841p:plain

f:id:min117:20191026215929p:plain

 

BASH_REMATCH初めて知った

qiita.com

f:id:min117:20191026223242p:plain

 

アンダーバーの後ろに日本語がくるファイル(レーザービームとか)もあるが、これを正規表現でひっかけるの癖がありそう

orebibou.com

 

と思ったらイッパツでできた。まじか。bash凄すぎるな。

$ for i in *Perfume*; do if [[ "$i" =~ .*Perfume[ぁ-ん] ]]; then echo "$i"; fi; done

f:id:min117:20191026221249p:plain

次回はファイル文字列中に含まれる不要な英数字の連続部分だけを除去する。

f:id:min117:20191026205714p:plain

これもfor文内部のif条件式の正規表現でファイルを捕まえてsedで処理させればいいだろうけど、sed内でも正規表現を使わないといけないから今回よりはちょっと難しいはず。次回試す。

 

min117.hatenablog.com

min117.hatenablog.com

min117.hatenablog.com