適当のごった煮

Pythonと境界標とQGISを中心にいろいろと

Pythonでフォルダ内検索

スポンサードリンク

Pythonでフォルダ内を検索するメソッドを調べ、tkinterで検索スクリプトを作成しました。

フォルダとファイルの一覧を得る

メソッド

モジュール表現結果の形式
os listdir([path]) リスト
os walk(top, topdown=True, onerror=None, followlinks=False) ジェネレータ(タプル)
glob glob(pathname, *, recursive=False) リスト

globは、ワイルドカードとrecursiveの指定次第で様々な出力結果を得られる。

出力比較

# 以下のようなフォルダで実験
\TEST
│  a.txt
│  dir_test.py
│
└─test2
    │  b.txt
    │
    └─test3
            c.txt
os.listdir
>>> os.listdir()
['a.txt', 'dir_test.py', 'test2'] # カレントディレクトリのフォルダとファイルのリストアップ
os.walk
>>> wk = os.walk('.')
>>> for line in wk:
    print(line)

# カレントディレクトリから下層まで探索してフォルダごとにリストアップ
('.', ['test2'], ['a.txt', 'dir_test.py'])
('.\\test2', ['test3'], ['b.txt'])
('.\\test2\\test3', [], ['c.txt'])
glob.glob
>>> glob.glob('*')
['a.txt', 'dir_test.py', 'test2'] # os.listdir()と同じ
>>> 
>>> glob.glob('**', recursive=True)
['a.txt', 'dir_test.py', 'test2', 'test2\\b.txt', 'test2\\test3', 'test2\\test3\\c.txt'] # 指定の方法を変えると下層まで探索

tkinterでGUIフォルダ検索スクリプトを作成する

コマンドプロンプトのfindのような動作をするスクリプトです。

拡張子を指定してファイル種別を選択。Windowsの場合、ユニコードで書かれたファイルはエラーになるので無視というか無理やり開いています。

Pythonスクリプトフォルダを検索する場合は、「open」で「encoding='utf-8'」を指定するように変更するか、「try」等をうまく使って処理すればよいと思います。

いくつか改善点はありますが、とりあえず動いたことに満足してそのままです。

f:id:tekito-gottani:20170107192124j:plain

f:id:tekito-gottani:20170107192137j:plain

# -*- coding: utf-8 -*-
import os
import tkinter as tk
import tkinter.filedialog as filedialog

class App(tk.Frame):
    def __init__(self, master = None):
        tk.Frame.__init__(self, master)
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        # ラベル
        self.lbl1 = tk.Label(self, text='検索対象フォルダ')
        self.lbl1.grid(row=0, column=0)
        self.lbl2 = tk.Label(self, text='拡張子')
        self.lbl2.grid(row=1, column=0)
        self.lbl3 = tk.Label(self, text='検索語')
        self.lbl3.grid(row=2, column=0)

        # フォルダ選択ボタン
        self.btn1 = tk.Button(self, text='フォルダ選択', command=self.btn_open_file)
        self.btn1.grid(row=0, column=2)

        # 検索ボタン
        self.btnf = tk.Button(self, text='検索', command=self.sagasu)
        self.btnf.grid(row=2, column=2)

        # エントリー
        self.ent1 = tk.Entry(self, width=50)
        self.ent1.grid(row=0, column=1)
        self.ent2 = tk.Entry(self, width=50)
        self.ent2.grid(row=1, column=1)
        self.ent3 = tk.Entry(self, width=50)
        self.ent3.grid(row=2, column=1)

        # テキストエリア
        self.text = tk.Text(self)
        self.text.grid(row=3, column=0, columnspan=4)

    # フォルダ選択メソッド
    def btn_open_file(self):
        self.ent1.delete(0, tk.END)
        self.ent1.insert(0, filedialog.askdirectory())

    # 検索ボタンメソッド
    def sagasu(self):
        if self.ent1.get() == '' or self.ent2.get() == '' or self.ent3.get() == '':
            self.text.insert('1.0', 'フォルダと拡張子と検索語を入力してください')
            return

        self.text.delete('1.0', 'end')
        kts = self.ent2.get()
        for dirpath, direnames, filenames in os.walk(self.ent1.get()):
            for name in filenames:
                if kts in name:
                    target = self.ent3.get()
                    filename = os.path.join(dirpath, name)
                    self.text.insert('end', '-----' + filename + '-----\n')
                    f = open(filename, errors='ignore')
                    for num, line in enumerate(f):
                        if target in line:
                            insert_line = str(num) + ':' + line
                            self.text.insert('end', insert_line)
                    f.close()

app = App()
app.mainloop()