2012年3月24日

たくさんのファイルをいっぺんにリネーム

きのうの隔週勉強会で「リネームソフトってWindows用ばっかりや」という声が(一部から)聞こえたけど*、Mac OS Xだと別段必要もないんじゃないかな。Windowsはシェルがしょぼいから、ファイルのリネーム程度のことでもソフトを作らなあかんということですよ。実際にはMac用のもたくさんあるようです。私がWindowsのこともMacのことも知らないだけでした^^)

OS Xはunixですから。


勉強会で出て来たのは、「感-5864.ai」という形式の名前を持つファイルを、冒頭の漢字1文字とハイフンまでを外した「5864.ai」という形式の名前にリネームしたい。たくさんあるのを一括処理したいという課題でした。

Terminal(shellはbash)でやれば簡単。
bashの「for name [ in word ] ; do list ; done」構文を使います。

sedでやってみる

まず、考えたのは手に馴染んでいるsedを使うやりかた。
for i in *.ai
> do
> cp $i `basename $i | gsed -e 's/^.-//'`
> done
  1. basenameコマンドでファイル名をテキストとして取得:basename $i
  2. それをパイプを通じてsedに渡し、
  3. 先頭の一文字とそれに続くハイフン(^.-)を削除:s/^.-//
  4. ここまでの実行結果(`basename $i | gsed -e 's/^.-//'`)を新しいファイル名としてcpコマンドに渡す
という手順。

ただし、漢字など多バイト文字はOS X付属のsedではうまく変換できないので、GNU sedが必要です。(bashの環境変数のうちLANGも、LANG=ja_JP.UTF-8とする必要があります)

perlをつかう

そこで、OS X付属のperlを使ってみました。こんな感じです。
for i in *.ai
> do
> cp $i `basename $i | perl -CIO -pe 'use utf8; s/^.-//;'`
> done

】当初、perl -pe 'use utf8; s/^.+-//;'」と書いていて、どうして「+」が必要なんだろうと不思議に思っていたのですが、エンコーディングの指定書式を旧式の「use encoding "utf8"」にすると文字数が思惑どおりになりました。しかし、その後、perlの起動オプション「-C」で出入力のエンコーディングを指定することを教わりました(man perlrun参照)。これでやっと現代的なコードになりました。みなさん、ありがとうございます。


bashだけでできる

そうこうしているうちに、bashだけでできるのに気付きました。こうです。
for i in *.ai
> do
> cp $i ${i/*-/}
> done

変数を展開する際にその一部を書き換える機能をbash自体が持っているんです。
bashのmanpageでは、「Parameter Expansion」項の最後の方に載ってます。
 ${parameter/pattern/string}という構文です。
(今回はpatternの文字列を削除するのでstring文字列は

検索パターンの書き方にちょっと癖があるし、機能もsedやperlほどではないのですが、今回のような事例ならこれで充分役立ちます。

2 件のコメント:

Unknown さんのコメント...

森さん、お世話になります。
use utf8;ではMacのファイルシステムで使われているUTF-8には聞かないが、use encodings "utf8"; では利いたということですね。
もっともメンテナーのダンさんによると、use encodingsは「黒歴史」であって使ってくれるなだそうです。
http://blog.livedoor.jp/dankogai/archives/51221731.html

TakSi MORI さんのコメント...

起動オプションでのエンコード指定を教わったので、非推奨の書き方を改めました。