python ファイル名に応じたフォルダ分け(ファイル整理術)
ファイル名に応じたフォルダ分け(ファイル整理術)
前回の投稿から大分日が経ってしまったが、今回は、カレンダーの続きはお休みにして、標記について記述したい。
なお、先月のアクセス数は、延べ7,713pv、2,695人であった。(1日平均約250pv)
こんなギークな記事にこれほどアクセスがあるものかと正直驚いているが、読者からコメントも頂き、非常に感謝である。
これを励みにギークな記事を発信し続けていきたい。(どれほど参考になっているかは不明であるが。。。)
本日は私が実務で多用しているpythonの使い方について紹介する。
後輩からもこのような「例題」についての質問をよく受けるため、ここで紹介したい。
例題:ファイル名に含まれている日付に基づきフォルダを作成し、そのフォルダに整理する
大量のファイルに対して次のような処理を行いたいことを想定する。
- ファイル名は、"YYYYMMDD_XXXXXX.txt"のように、日付とタイトルがある
- ファイル名の日付に基づき、日付フォルダを作成し、そのフォルダに当該ファイルを格納する
ロジック
今回のロジックを整理すると、次の4つの処理が必要となる。
- 整理したいファイル名の取得
- for文によりファイル名を1つずつ取り出す
- 取り出したファイル名から日付を切り出す
- 日付フォルダを作成し、ファイルをその日付フォルダに移動
1.整理したいファイル名の取得
フォルダ内のファイル名を取得したい場合は、 os.listdir() を用いる。
これは、引数に指定したフォルダにあるファイル名をリスト型で返してくれる。引数を省略すると、カレントディレクトリが暗黙的に指定される。
後の処理のためにも、ファイル名を取得したいフォルダをカレントディレクトリに設定しておきたい。
※python3のインタプリタで実行(python2でも動くはず。以下同じ)
import os os.chdir(r"C:\Users\00000000\Desktop\pywork") files = os.listdir() print(files)
ファイル名のリストを取得できた。
2.for文によりファイル名を1つずつ取り出す
リストの状態ではその後の処理ができないため、これをfor文により1つずつ取り出し、その取り出したファイル名に対して処理を行う。
まずは、print()ファンクションで、ファイル名を取り出せるか試すのが常である。
for file in files: print(file)
3.取り出したファイル名から日付を切り出す
次に、取り出したファイル名から日付部分のみ切り出す。今回は、固定長(ファイル名の日付部分がすべて同じ文字数)のファイルを想定しているが、これが不定長の場合には、正規表現などを駆使して、別途、任意の文字列を切り出すためのロジックを考える必要があるが、今回の記事では割愛する。
今回は、単純に文字列のスライスを用いる。
for file in files: print(file[:8])
日付部分のみ取り出せた。
4.日付フォルダを作成し、ファイルをその日付フォルダに移動
今回のポイントはこのロジックである。
osモジュールにはフォルダを作成するファンクション os.mkdir() が用意されているが、これを用いることはお勧めしない。なぜならば、 os.mkdir() は、作成したいフォルダが既に存在する場合にエラーを返すため、条件分岐構文によりそのフォルダが存在するかどうか事前に確かめるか、try-except文によりエラーをスキップするロジックを組まなければならないため、文が複雑になる。
これを回避し、かつ、ファイルの移動もまとめてやるのが、 os.renames() である。
# ファイルのパス名をoldからnewへ変更する
os.renames(old,new)
これを持ち出すと後輩にも、「ファイル名を変更するやつですよね?」と聞かれるが正しくない。これは、「ファイル名」も結果的に変更することができるが、正しくは、「パス名」を変更するものである。
そして、変更後のパスに、中間のフォルダが存在しない場合、 os.renames() を用いれば、暗黙的にそのフォルダを作成してくれるのだ。
これを先のfor文に組み込むと次のようになる。
for file in files: os.renames(file,file[:8]+"\\"+file)
これで、全てのファイルを日付フォルダに格納することができた。
ちなみに、 os.renames() と似たようなものに、 os.rename() が存在する。両者の違いは、中間に存在しないフォルダがある場合に、 os.renames() は暗黙的にフォルダを作成し、 os.rename() はエラーを返すという振る舞いをする。