ファイルの一括リネーム - UNIX哲学的アプローチ

ファイルの一括リネーム。皆さん悩ましいですね。

単にリネームだけじゃなくてファイルの移動なども同時に実行となると、なかなか適合するものがありません。 一番しっくりくるのは EmacsのDiredなんですが、それだけのためにEmacsを使うのはちょっと…

Emacsは10年前に卒業して以来全く触ってません。当時MeadowNTEmacsにはお世話になりました)

その他、多種多様なツールがありますが、どれも僕の好みではありませんでした。

何か良いのは無いんかい、と思いつつググると、renameというコンドラインツールは見つかったものの、 それよりも僕に刺さったのが、毎度おなじみStackOverflowのこの投稿。

stackoverflow.com

つまりこういうこと。

f:id:takahashikzn:20201004115028p:plain

素晴らしいですね。なんで思いつかなかったんだろう。バッチ操作のスクリプトワンライナーで生成してshに流せばいいだけ。

というわけで、サクッとこんな風に書いて

find . -name '*.xlsx' -or -name '*.json' \
| perl -pe 's!(.*)/(\d+)\.(\d+)\.(\d+)_([^/]+)$!cp $& ../out/$2_$3_$4_$5!g' \
| perl -pe 's/(.+)-([^-]+)$/$1_$2/g' \
| sh

やりたいことが出来るようになりました。

shに流さず一旦テキストファイル化するだけでdry-run*1ですし、 ワンライナーでは難しいような込み入った操作であれば、それを好きに編集してから sh に流せばいいだけ。

っていうか、これが由緒正しい本来のshの使い方そのものかと。

ちなみに上記の意味を解説しておくと、

  1. ディレクトリを再帰的にたどり、
  2. 1.2.3_あいうえお.xlsxないし1.2.3_あいうえお-1.jsonというファイルの名前を1_2_3_あいうえお.xlsx1_2_3_あいうえお_1.jsonに変換して、
  3. ../out へコピーせよ

です。

*1:実際には実行せず、何が起きるか確認だけする行為