元セブ島在住のエンジニアの僕「Tommy」が、プログラミング・英語・セブ事情を発信するブログ

Tommy's blog

【Python】globを用いたファイルの検索方法【→プログラム初心者向け】

11月 26, 2019

プログラム学生
ファイルの拡張子で検索することってできますか?
ファイル名の一部が分かっているファイルをすべて検索するってことだね。これはPythonのglobってライブラリの関数を使うとできるから、これを説明するね。
Tommy

この記事で分かること

  • ディレクトリとファイルに仕分けしてくれる「walk」の使い方が分かる
  • 引数で指定したパターンに応じたファイルパスを取得できる「glob」の使い方が分かる
  • ディレクトリとファイルの一覧を作成する方法が分かる

Pythonのglobを用いたファイル検索方法の概要

この記事では、Pythonのglobを使って、全てのサブフォルダ、ファイルを検索する方法を説明します。これにより、特定の文字で始まるファイルや特定の文字で終わるファイルなど、自分が検索したい文字が含まれているファイルだけを検索することができ、さらに、自分が検索したい文字が含まれているファイルだけのファイルリストを作ることができます。

Pythonのglobを用いたファイル検索方法の前提環境

Pythonで特定のファイルを再帰的に検索する前提の環境は、下の記事で説明している私の環境と同じ環境で確認しています。

レンタルサーバなどのLinuxサーバを使っている場合は、下の記事でプログラミングする環境の作り方を説明しています。

もし、まだプログラムする環境ができていない方は、先にこちらの記事を読んで、プログラミングできる環境をつくることをおすすめします。

Pythonのglobを用いたファイル検索方法のサンプルプログラム

ここでは、カレントディレクトリの配下のフォルダや指定された名前のファイルをすべて取得するサンプルプログラムを書いていきます。

サンプルプログラムの作成

カレントディレクトリの配下のフォルダや指定された名前のファイルをすべて取得する為には、まず指定されたディレクトリ(フォルダ)の中に存在するファイルをすべて取り出す関数を定義し、その関数からの戻りを所望のファイルだけを選び取る作業(フィルタリング)を実施する必要があります。所望したファイルだけを選び取るフィルタリングを行う為には、それ専用のライブラリをインポートするほうが便利です。

以上の処理を行うサンプルプログラムは次のような順番で説明します。

  1. ライブラリのインポート
  2. 全てのフォルダパスを返す関数の定義
  3. globを使用したファイルリスト化

1.ライブラリのインポート

指定ディレクトリの中身をフォルダとファイルに仕分けしてくれる「walk」とよばれる関数を利用する為に、「os」ライブラリをインポートしています。また、引数で指定したパターンに応じたファイルパスを取得できる「glob」と呼ばれるメソッドを使う為にライブラリ「glob」をインポートしています。

import os
import glob

2.全てのフォルダパスを返す関数の定義

ここでは、全てのフォルダパスを返す関数「find_all_dirs」を定義します。「os.walk」は引数に指定したディレクトリの現在のディレクトリ、その配下のサブディレクトリ、ファイル名をリスト形式で取得できる関数です。

ここで定義した「find_all_dirs」は「os.walk」から「cur_dir」が帰って来たら都度、「find_all_dirs」の呼び元へ値を返すことになります。これは「yield」の働きなのですが、「yield」については下の記事で説明していますので、下の記事を参考にして下さい。

def find_all_dirs(directory):
	for cur_dir, dirs, files in os.walk(directory):
		yield cur_dir

  1. 関数「find_all_dirs」を定義宣言する。
  2. 変数「directory」を関数「os.walk」を使って「cur_dir」「dirs」「files」にそれぞれ抽出しながら、for文の中身を繰り返す。
  3. 変数「cur_dir」をyieldで返却する。

3.globを使用したファイルリスト化

上で定義した関数「find_all_dirs」で得られたディレクトリのリストに対して、「file」と名前の付くファイルだけのパスを取得して表示しています。「glob」は引数に、フォルダパスやファイル名を入力すると、リスト形式で返してくれる関数です。

このサンプルプログラムでは、「dir+'/'+'file*'」と入力していますが、関数「find_all_dirs」で得られたフォルダパスの下のファイルの名前の先頭が「file」であるファイルだけをリスト形式で返すようにしています。

if __name__ == '__main__':
	for dir in find_all_dirs('./'):
		for file in glob.glob(dir+'/'+'file*'):
			print(file)

  1. 関数「find_all_dirs」の引数に現在のディレクトリ「./」を設定した結果を変数「dir」に格納しながら、forを繰り返す。
  2. 関数「glob.glob」の引数にディレクトリが入った変数「dir」と「fle」という名前で始まるファイルを指定し、出てきたファイルを1つずつ変数「file」に格納しながら、for文を繰り返す。
  3. 変数「file」の内容を表示する。

サンプルプログラム実行の結果

上で作成したサンプルプログラムの実行結果が下の表示です。カレントディレクトリ配下には「file1」と「file2」というファイルと、「dir1」といフォルダがあり、「dir1」の下には「file3」と「file4」というファイル、「dir2」というフォルダ、さらに、「dir2」フォルダの中には「file5」と「file6」というファイルがあることが分かります。

$python test.py
./file2
./file1
./dir1/file3
./dir1/file4
./dir1/dir2/file6
./dir1/dir2/file5