【Python】ファイル検索アプリ開発:フォルダ内から指定ファイルを検索(globモジュール)

2020.12.12 /

【Python】ファイル検索アプリ開発:フォルダ内から指定ファイルを検索(globモジュール)

仕事で大量のファイル・フォルダの中から特定の文字を含んだファイルをWindowsのエクスプローラーで検索をかけることがよくあります。

これをPythonで作成したアプリで再現してみたいと思います。

そこで本記事では、Pythonでファイル検索機能を実装したアプリケーションの作成について解説します。
Windowsエクスプローラーの検索機能のように、指定した文字列を含むフォルダやファイル検索できるアプリケーションを開発します。

この方法を応用すれば、様々なアプリ開発に活用することができます。
私も仕事で今回紹介する方法を多くのアプリに使用しています。

また本記事で作成するアプリケーションにはglobモジュールを使用しています。
globモジュールはファイル操作で活躍するモジュールであり、使い方を覚えることでファイル操作が非常に簡単になります。

globモジュールの使い方から、Tkinterを使用したファイル検索機能を持ったGUIアプリケーション開発まで説明していきます。

globモジュール

globモジュールとは

globモジュールは、
ワイルドカードを使用したパターンに従って、該当するファイルのパスを返します。

globモジュールは様々な用途で使用されます。

  • 任意の文字列から始まるファイルパスを取得
  • 検索したいファイルの拡張子を指定して、該当するファイルのファイルパスを取得
  • フォルダ内のファイル・フォルダのパスをすべて取得

Pythonでのフォルダ・ファイル操作や検索に活躍するモジュールと言えます。

globモジュールのインポート

globモジュールは標準ライブラリに含まれるため、pipでインストールする必要はないです。

Pythonファイルで使用するためには、先頭でglobモジュールをインポートする必要があります。

  • import glob

glob.glob()関数

globモジュールのglob()関数を使用して、引数に指定したパスとマッチするファイルやフォルダ(ディレクトリ)をリストにして返します。

  • glob.glob(path, *, recursive=False)

第一引数に検索したいパスを指定し、それにマッチするファイルやフォルダ(ディレクトリ)のパスを要素とするリストで返します。

glob.glob()はリストで返すため、for文による繰り返しがよく使われます。

  • for file in glob.glob(path)

glob.glob()の引数にはワイルドカードを使用します。
ワイルドカードについては次節で説明します。

ワイルドカード

ワイルドカードとは、特定のパターンに一致する文字列の指定・探索に使用します。
文字列のパターンを指定する正規表現で使われています。

glob()で使うワイルドカードには「*、?、[-]」の特殊文字があり、任意の文字列を表します。

記号 意味
0文字以上の任意の文字
任意の1文字
[-] []に含まれる1文字

例えば、office.txtをワイルドカードで指定するには以下の方法が挙げられます。

  • *.txt
  • ?????.txt
  • [a-o]*.txt

glob.glob()の引数では、これらワイルドカードを巧みに用いて、検索したいファイル・フォルダを指定します。

glob.glob()による検索方法

検索:フォルダ内のすべてのファイル・フォルダ

glob.glob()で指定したフォルダ内すべてのファイル・フォルダのパスを取得するには以下のようにします。

import glob

path = "C:\OFFICE54"

for file in glob.glob(path + "\*"):
    print(file)

上記サンプルプログラムでは、glob.glob()の引数にワイルドカード*を用い、OFFICE54フォルダ内のすべてのファイル・フォルダをリストで返し、それをfor文の繰り返しでprintして表示しています。

検索:拡張子で絞り込み

glob.glob()でフォルダ内の指定した拡張子で絞り込むには以下のようにワイルドカードを用いて検索します。

import glob

path = "C:\OFFICE54"

for file in glob.glob(path + "\*.xlsx"):
    print(file)

上記サンプルプログラムでは、glob.glob()の引数にワイルドカード*と拡張子を組み合わせることで、OFFICE54フォルダ内の拡張子xlsxのファイルをリストで返しています。

検索:任意の文字列から始まるファイル名

glob.glob()でフォルダ内の任意の文字列で始まるファイルを検索するには以下のようにワイルドカードを用いて検索します。

import glob

path = "C:\OFFICE54"

for file in glob.glob(path + "\OFFICE*.xlsx"):
    print(file)

上記サンプルプログラムでは、glob.glob()の引数に任意の文字列とワイルドカード*を組み合わせることで、OFFICE54フォルダ内の任意の文字列で始まるファイルをリストで返しています。

任意の文字列で終わるファイルを検索するには以下のようにします。

  • glob.glob(path + "\*OFFICE.xlsx")

検索:フォルダ内のサブフォルダ

指定したフォルダ内のサブフォルダを検索対象にするには以下のように記述します。

import glob

path = "C:\OFFICE54"

for file in glob.glob(path + "\*\*"):
    print(file)

glob.glob()の引数に「\*\*」とすることで、一つ下の階層のファイル・フォルダを対象にできます。

検索:フォルダ内+サブフォルダ内

フォルダ内とサブフォルダ内の両方を検索の対象にしたい場合は、glob()の引数recursiveをTrueにし、特殊文字**を使用します。

recursiveとは「再帰的」という意味であり、「OFFICE/**/*.txt」とすると、**のフォルダ内も含めて(再帰的に)*.txtを検索できます。

import glob

path = "C:\OFFICE54"

for file in glob.glob(path + "\**\*.xlsx", recursive=True):
    print(file)

# C:\OFFICE54\OFFICE54.xlsx
# C:\OFFICE54\OFFICE54\OFFICE55.xlsx

上記サンプルプログラムを実行すると、サブフォルダも含めた検索ができるようになります。

対象フォルダだけでなく、サブフォルダも含めて検索を広げたい場合に有用な検索方法です。

検索:ファイルのみ

フォルダを含まないファイルのみを取得したい場合は、osモジュールのos.path.isfile()を使用します。

import glob
import os

path = "C:\OFFICE54"

for file in glob.glob(path + "\*"):
    if os.path.isfile(file):
        print(file)

拡張子で絞り込むのではなく、すべてのファイルを取得したい場合に使用します。

検索:フォルダ(ディレクトリ)のみ

ファイル(ディレクトリ)のみを取得したい場合は、osモジュールのos.path.isdir()を使用します。

import glob
import os

path = "C:\OFFICE54"

for file in glob.glob(path + "\*"):
    if os.path.isdir(file):
        print(file)

GUIアプリ開発

アプリ概要

ここまで紹介したgrid.grid()とTkinterを使って以下のようなGUIアプリケーションを作成してみます。

PythonでのGUIアプリ:ファイル検索アプリ
  1. 「フォルダ検索」ボタンを押すと、フォルダ検索ダイアログが表示します
  2. 対象のフォルダを選択すると「フォルダ検索」の入力欄にパスが挿入されます
  3. 検索したいファイル・フォルダの文字列を「検索文字」の入力欄に入力します
  4. 「ファイル検索」ボタンを押下すると、検索結果が表示されます
PythonでのGUIアプリ:検索値入力
PythonでのGUIアプリ:結果

Tkinterの使い方については以下リンクをご参照ください。

ソースコード

アプリ概要で紹介したGUIアプリのソースコードを以下に記します。
ぜひコピペしてどのように動くのか確認してみてください。

# sample.py
import glob
import os
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import filedialog
from tkinter import messagebox

def dir_search():
    fld = filedialog.askdirectory()
    entry_path.insert(tk.END, fld)

def file_folder_search():
    path = entry_path.get()
    char = entry_char.get()
    files = ""
    for file in glob.glob(path + "\*" + char + "*"):
        files = files + file.replace("/", os.sep) + "\n"
    messagebox.showinfo("検索結果", files)

# rootメインウィンドウの設定
root = tk.Tk()
root.title("tkinter application")
root.geometry("320x100")

# メインフレームの作成と設置
frame = ttk.Frame(root)
frame.pack(fill = tk.BOTH, padx=20,pady=10)

# 各種ウィジェットの作成
label_path = ttk.Label(frame, text="検索フォルダ:")
entry_path = ttk.Entry(frame)
button_folder = ttk.Button(frame, text="フォルダ検索", command=dir_search)
label_char = ttk.Label(frame, text="検索文字:")
entry_char = ttk.Entry(frame)
button_search = ttk.Button(frame, text="ファイル検索", command=file_folder_search)

# 各種ウィジェットの設置
label_path.grid(row=0, column=0)
entry_path.grid(row=0, column=1)
button_folder.grid(row=0, column=2)
label_char.grid(row=1, column=0)
entry_char.grid(row=1, column=1)
button_search.grid(row=2, column=1, pady=10)

root.mainloop()

配布用のexeファイルにする

作成したPythonファイルを他の人にも配布できるようにexeファイルにします。

exeファイルにすることで、Pythonをインストールしていない人でも簡単に作成したアプリケーションを起動できるようになります。

Pythonのpyinstallerを使用したexeファイル作成方法は以下記事をご参照ください。

まとめ

Pythonでのファイル検索アプリ開発はいかがでしたか。

フォルダ内からファイル・フォルダを検索するなどのファイル操作はPythonでよく使います。
今回紹介したglobモジュールの使い方をマスターして、ぜひ仕事で活用してください。