rock2016-05-18バッチ処理で複数ファイルを一気にリネームするPerlスクリプトを書いたperl昨日の業務中、「普段はあまり遭遇しないがまれに生じる面倒な手作業」に遭遇し、「あ〜この作業、前から専用スクリプトで一括で済ませたいと思ってたんだよな〜」と思ったので、一旦作業の手を止めて猛然とコードを書いてみたら、それで問題をクリアできてしまった。普段ならわざわざ作業の手を止めてまでコードを書くなんてことはなくて、「あ〜これコードで自動化したい......けどそんなの作り始めたらいつ終わるかわかんないから、残念だけど今はとりあえず手でやってしまって、あとで時間ができたらこれをお題に書いてみよう〜」なんて後回しにするものの、実際には当の問題が解消されてしまうとなかなかそのモチベーションも湧かなくて、結局いつまでたっても「あ〜これいつもの面倒なやつ......でも今はとりあえず手でやっておいて......」などと同じつらさの繰り返しに陥るところ、どうもこの数ヶ月は自分で書いたツールを使う機会が以前よりだいぶ増えてきたので、やればできるかなあ、という淡い自信に後押しされてガッと作ってみた。やったことは大まかに言って、最近自分の中で流行ってる「ファイルのリネーム」なのだけど、以前にここで紹介した同類のツールだと、note103.hateblo.jpあまり大がかりな変更はできないというか、基本的には数文字ちょろっと変えたい、みたいな用途で生きてくるものなので、今回の目的からはちょっとズレていた。ぶどう.mdこれを以下のようにリネームしたい、みたいな。mdなど)はそのままで、名前もほとんど同じなんだけど、変更する際の規則性が弱いので、これを上記のツールでやろうとするとそれはそれで面倒というか、この状況ならコード使わずに手でやっちゃったほうがマシ......という感じにどうしてもなってしまう。いえ、上記はあくまでサンプルなのでほんの数ファイルしかないけれど、昨日の本番状況ではこういうリネームしたいファイルが20点以上あったので、これ......このまま手でやるのは不毛すぎる......頑張って終わらせてもあまり達成感なさそう......というか人間がやってはいけない......などと思ってコードに向かってみたという。以上のような前提を踏まえて、まず考えたのは、今回は以前のような標準入力方式(ターミナルに対話形式で打ち込むやつ)ではなく、リネーム後の文字列を事前にファイルに記述しておいて、それを読み込ませて動かすバッチ処理方式でいくべきだろう、ということ。そのためにすぐ着手できそうなのは、とりあえず変換後のテキストファイル(バッチファイル)を作ること。ぶどう.mdこれが書かれたファイルを作る。1_りんご.mp32_ばなな.m4a3_みかん.mp34_れもん.txt5_ぶどう.mdということで、とりあえずFinderで該当ファイルを選択&コピーして......エディタにペーストすると......おっと......なにこの崩れ......。ああ〜、それか〜......って。以前、ここでちらっと呟いたのだけど、MacでPDFをコピペしたときに濁点などのある文字が壊れるのが困るケースが時々あったけど、ここにある「Unicode::NormalizeのNFC関数」というのを通したら無事普通になった。2016いつも『CPANモジュールガイド』でお世話になっていますトミールさんの以下のブログ記事で解説されている、「UnicodeのNFDという正規化」の問題みたい。Macのファイル名はNFDされているMacOSXでは文字コードはutf-8エンコーディングが使われているのだけど、UnicodeのNFDという正規化がされている。゙」の二つのUnicodeで表現されたりしてる。゙は「てん」で変換してでる濁点マーク(U+309B)ではなく、Unicodeで組み合わせる用として用意されている点(U+3099)。Macだと時々これに遭遇して、ぐむむ......ってなる。他のケースでありがちなのが、そのTwitterでも書いているけどPDFからテキストをコピペした時とか。じつは今回の件においては、この崩れは見なかったことにして進めてしまってもとくに問題なかったりするのだけど、上記のトミールさんの記事をもとにこの崩れを直すコードも書いてみた。実行している様子*1。そのように抜き出したテキストを元に、変更後のテキストを作成。1_りんご.mp32_ばなな.m4a3_みかん.mp34_れもん.txt5_ぶどう.mdそいつをconv.txtとかにしておいて......このような変換スクリプトを書いてみた。動かしてみると......。ん、あ、ちょっと待った。れもん.txtto:1_りんご.mp32_ばなな.m4a3_みかん.mp34_れもん.txt5_ぶどう.md微妙にファイルの順番が違う......。上(from:)は辞書順、つまり行頭の数字が小さい順に並んでしまっていて、数値(108とか14とか)の順番で並んでいない。前掲のようにMacのFinderで見ると、こっちは数値順で並んでるわけで......これを元に変換後のリストを作ったからズレたみたい。紛らわしい......けど、もうここは僕には良い方法が見つからなかったので、諦めてバッチファイルの方をそれに合わせて並べ直すことに。conv.txt1_りんご.mp35_ぶどう.md3_みかん.mp32_ばなな.m4a4_れもん.txtん〜、バッドノウハウ的で腑に落ちないが、これで中身がメチャクチャになることはないはず。動かしてみると......。OK!って、これだとちゃんと中身が同じで名前だけ変わったのかどうか、わかりづらいですが、まあ大丈夫でした。(雑)ちなみに、元々の目的はリネームなので、元ファイル自体の名前を変えても良かったのだけど、上記のようにバッチファイル(conv.txt)の指定が間違っていた場合、元ファイルが消えてしまうとけっこう面倒なので、元ファイルはそのまま残して、目的のファイル群は別ディレクトリ内に別名でコピーするようにしています。これなら、万一指定を間違えてもコピー先を削除して、バッチファイルを修正後にまた処理すればよいので。あと、バッチファイル上のファイル名と、コピー元のファイル群の数が異なる場合は、指示が間違っている可能性が高いので、処理する前にdieするようにしています。ぶどう.mdバッチファイルをこんな感じにしておくと......(6番を追加)1_りんご.mp35_ぶどう.md3_みかん.mp32_ばなな.m4a4_れもん.txt6_かき.txtこんな感じに。途中で終わってくれる。その他、現状だとコピー先のディレクトリにすでにコピー予定のファイル名が存在していたら上書きしてしまうので、それを避けるようにしたほうがいいんじゃないかとか、あるいは現在のコードだとmp3をテキストファイルにしたり、Excelファイルを.pdfにしたりとかいう奔放なことを平気でやるので(もちろん中身はメチャクチャになる)、拡張子をチェックしてファイルの種類が違ったらエラーを出すとかの機能も考えたのだけど、今回の仕様としては完全なリネームではなくコピーなので、そこまでやらなくていいか、と。なにより、この内容でそもそもの目的だった20数点のファイル一括リネームもできたので、ひとまずヨシとしたいと思います。さんから、glob関数の使い方ファイル群を読み込む際に数値順で統一する方法などについて教えて頂きました。ありがとうございます!!ということで、それらを参考に以下のように直してみました。GitHubdiffスッキリ&直感的!になりました。数値順になってることを示した後、処理をやってます。具体的な使い方で詰まった際、こちらもいつもお世話になっています木本裕紀さんのサイトにて、理解を補いました。Perlプログラミングの基礎から応用までPerlに関するさまざまな情報が広く&深く&わかりやすく説明されていて、大変ありがたいです。)スターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。