Pythonで全ファイルに何かする、たとえば改行コード変換
日常の便利ツールPythonですが、いつもの頻出タスク、「全ファイルに何かする」をやるとき、いちいち書いていた(書きはじめが書きやすすぎて)のですが、あまりにも頻出するので、もういっそ、最小基本パターンを決め、今後書き換えて使う基本形にしようと決めました。
で、2.6以降だと決め込んで書いたのですが、これがけっこう短くなったので、紹介します。コードは「全ファイルの改行コードをCRLFからLFに変換して上書き」の例です。
import sys, os from itertools import imap #for only 2.x def iterfiles(basedir): for (path, dirs, files) in os.walk(basedir): for fn in files: yield os.path.join(path, fn) if len(sys.argv) < 2: raise RuntimeError("No folder specified to convert.") for fpath in iterfiles(sys.argv[1]): with open(fpath) as f: txt = "\n".join(imap(lambda line:line.rstrip("\r\n"), f)) with open(fpath, 'wb') as f: # 'b' for windows stdio f.write(txt)
ファイルを開くときのwithが効いていますね。行が複数に分かれないので、行挿入で改造するとき安心です。
また、フォルダ以下の対象ファイルを集めるという概念をiterfilesとしてひとくくりにしています。個々のファイルに処理したい内容と分けてあるので、ファイルの集め方だけをカスタマイズするとき、気楽です。やりすぎるとインターフェースのほうがややこしくなるので、このぐらいで十分。
エラー処理、「例外を吐いて補足しない」のは、人が使ったとき適切なエラー報告を受けることができるんで、身内用としては、最小労力で最大効果なのかなと思って、けっこう気に入ってる方法です。
うーん、importしなくてもfunctoolsのpartialやstringの関数が使えたら、lambdaにしなかったんだけどなぁ。2行もimportに増えるよりは、lambdaでいいや、という妥協。もし上のコードが好みじゃない方がいたら、こんなふうにもできますね。
txt = "\n".join(imap(partial(rstrip, "\r\n"), f))