【Python】フォルダ内のすべてのファイルのうち、特定の文字列が含まれているものを抽出する

Pythonでフォルダ内のすべてのファイルのうち、特定の文字列が含まれているものを抽出する方法です。

Python 3.7.2

特定の文字列が含まれているものを抽出する

まず普通に特定の文字列が含まれているものを抽出する方法です。
文字コードが違っているファイルが含まれる場合はうまくいかないので次節の方法を使ってください。

#coding:utf-8
import pathlib

# 特定の文字列が含まれているかどうか特定フォルダ内のすべてのファイルについて検索
def search_string(root_folder_path, search_word, extension = ""):
    if extension != "" and not extension.startswith("."):
        extension = "." + extension
        
    folder = pathlib.Path(root_folder_path)
    file_paths = folder.glob("**/*" + extension)
    for file_path in file_paths:
        # フォルダだったら飛ばす
        if file_path.is_dir():
            continue
        # ファイルを開く
        with open(file_path) as file:
            lines = file.readlines()
            # 行数を得るために一行ずつこの用にループ
            for i in range(len(lines)):
                # 改行記号を外す
                line = lines[i].strip()
                if search_word in line:
                    print(str(file_path) + "(" + str(i + 1) + ") : " + line)

文字コードが違って読み取れない文字を無視する

前節の方法では文字コードが異なるファイルが含まれている場合にうまくいきません。
そこで、文字コードが原因で読み取れない文字を無視します。
これはcodecsを使うことで実現できます。

#coding:utf-8
import pathlib
import codecs

def search_string(root_folder_path, search_word, extension = ""):
    if extension != "" and not extension.startswith("."):
        extension = "." + extension
        
    folder = pathlib.Path(root_folder_path)
    file_paths = folder.glob("**/*" + extension)
    for file_path in file_paths:
        # フォルダだったら飛ばす
        if file_path.is_dir():
            continue
        # ファイルを開く(文字コードが違ったら無視)
        with codecs.open(file_path, 'r', 'utf-8', 'ignore') as file:
            lines = file.readlines()
            # 行数を得るために一行ずつこの用にループ
            for i in range(len(lines)):
                # 改行記号を外す
                line = lines[i].strip()
                if search_word in line:
                    print(str(file_path) + "(" + str(i + 1) + ") : " + line)

正規表現を使う

さらに正規表現を使ってみます。
これである程度どんな検索でも自由にできるはずです。

#coding:utf-8
import pathlib
import codecs
import re

def search_string(root_folder_path, pattern, extension = ""):
    if extension != "" and not extension.startswith("."):
        extension = "." + extension

    # 正規表現をコンパイル
    repattern = re.compile(pattern)
        
    folder = pathlib.Path(root_folder_path)
    file_paths = folder.glob("**/*" + extension)
    for file_path in file_paths:
        # フォルダだったら飛ばす
        if file_path.is_dir():
            continue
        # ファイルを開く(文字コードが違ったら無視)
        with codecs.open(file_path, 'r', 'utf-8', 'ignore') as file:
            lines = file.readlines()
            # 行数を得るために一行ずつこの用にループ
            for i in range(len(lines)):
                # 改行記号を外す
                line = lines[i].strip()
                if repattern.search(line) != None:
                    print(str(file_path) + "(" + str(i + 1) + ") : " + line)