この記事で分かること
- フォルダが階層構造になっている場合のファイルを検索方法が分かる
- サンプルプログラムでファイル検索の具体的な方法が分かる
Pythonで再帰的にファイル検索する概要
Pythonプログラムを使って、あるフォルダの下にあるファイルを検索したい場合、Pythonでは、「os」ライブラリというものを使って、フォルダの中身を再帰的に検索することができます。
「再帰的」というのは、1つのフォルダの中身を調べるだけでなく、フォルダの中にあるフォルダの中身も繰り返し調べるという意味です。この記事では、Pythonで指定ディレクトリの下を、再帰的にファイル検索する方法を説明します。
Pythonで再帰的にファイル検索する前提環境
Pythonでフォルダの全ファイルを再帰的に検索する前提の環境は、下の記事で説明している私の環境と同じ環境で確認しています。
レンタルサーバなどのLinuxサーバを使っている場合は、下の記事でプログラミングする環境の作り方を説明しています。
もし、まだプログラムする環境ができていない方は、先にこちらの記事を読んで、プログラミングできる環境をつくることをおすすめします。
Pythonで再帰的にファイル検索するサンプルプログラム
ここでは、カレントディレクトリの配下のフォルダやファイルをすべて取得するサンプルプログラムを作成して、そのプログラムの実行結果を説明します。
再帰的にファイル検索するサンプルプログラムの作成
まず、カレントディレクトリの配下のフォルダやファイルをすべて取得するサンプルプログラムは次の順番で作成します。
- ライブラリのインポート
- 指定ディレクトリのファイルを再帰的に検索する関数の定義
- 定義した関数の呼び出し
ライブラリのインポート
ファイル名とディレクトリパスを操作する関数を使う為に、「os」という名前のライブラリをインポートします。
import os
「os」ライブラリをインポートする。
指定ディレクトリのファイルを再帰的に検索する関数の定義
下のプログラムでは、指定されたディレクトリ配下のファイルをファイルパスを含めてリストで返す関数「find_all_files」を定義しています。
osライブラリの「walk」という関数を使用して、現在のディレクトリにあるファイルを、現在のディレクトリ、そのディレクトリにあるサブディレクトリ、ファイル名に分解して、全てのファイルやサブディレクトリの個数分だけループします。
さらに1つ目のループで抽出されたファイル個数分だけ、ファイル名とディレクトリパスを連結し、「yield」で随時取り出すという処理を行っています。もし、「yield」について詳しく知りたい場合は下の記事を読んでください。
def find_all_files(directory):
for cur_dir, dirs, files in os.walk(directory):
for file in files:
yield os.path.join(cur_dir, file)
- 関数「find_all_files」を定義の宣言する。
- 引数「directory」で得られるディレクトリのパスから「os.walk」関数を使って、現在のディレクトリ、現在のディレクトリ配下のディレクトリ、ファイル名を変数「cur_dir」と変数「dirs」と変数「files」にぞれぞれ格納してFor文の内容を繰り返す。
- 「files」の変数「file」に格納してFor文の内容を繰り返す。
- 関数「path.join」から「yield」を用いて、都度ファイルパスを返却する。
定義した関数の呼び出し
関数「find_all_files」で得られたディレクトリのリストに対して、それぞれを表示しています。
if __name__ == '__main__':
for file in find_all_files('./'):
print(file)
- 現在のディレクトリを表す「./」を引数に、関数「find_all_files」の結果を「file」に入れてfor文の中身を繰り返す。
- 変数「file」の内容を表示する。
実行結果
上で作成したサンプルプログラム「test.py」を実行した結果が下の表示です。カレントディレクトリ配下には、「test.py」というサンプルプログラムのソースコードファイルと、「file1」と「file2」というファイル、さらに「dir1」といフォルダがあり、フォルダ「dir1」の下には「file3」と「file4」というファイル、「dir2」というフォルダ、さらに、フォルダ「dir2」の中には「file5」と「file6」というファイルがあることが分かります。
$ python test.py
./test.py
./file2
./file1
./dir1/file3
./dir1/file4
./dir1/dir2/file6
./dir1/dir2/file5