Skip to content

pythonファイルを検索#

ファイル名を検索#

特定のファイル名がつくファイルを検索するためには、Pythonの標準ライブラリであるosモジュールを使用します。以下は、ディレクトリ内で特定のファイル名を持つファイルを検索するための基本的なコード例です。 上記のコードを使用して、指定したディレクトリ内で特定のファイル名を持つファイルを検索し、そのパスを表示することができます。

search_file.py
import os
import sys

def search_files(directory, keyword):
    matching_files = []

    for root, dirs, files in os.walk(directory):
        for file in files:
            if keyword in file:
                matching_files.append(os.path.join(root, file))

    return matching_files

def main():
    if len(sys.argv) != 3:
        print("Usage: python script.py <directory_to_search> <file_keyword>")
        return

    directory_to_search = sys.argv[1]
    file_keyword = sys.argv[2]

    result = search_files(directory_to_search, file_keyword)

    if result:
        print("Matching files found:")
        for file_path in result:
            print(file_path)
    else:
        print("No matching files found.")

if __name__ == "__main__":
    main()

上記のコードをスクリプトとして保存し、ターミナルから以下のように実行します。

python search_file.py /path/to/search target_filename
ここで、script.pyは保存したPythonスクリプトのファイル名です。/path/to/searchとtarget_filenameはコマンドライン引数として渡すディレクトリとキーワードに置き換えてください。

高速化#

ファイルを高速に検索するために、マルチスレッドを使用する方法があります。Pythonのconcurrent.futuresモジュールを使用して、並行して複数のファイル検索タスクを実行することができます。 以下は、マルチスレッドを使用してファイル検索を高速化するコード例です。

import os
import sys
import concurrent.futures

def search_files_in_directory(root, keyword):
    matching_files = []

    for dirpath, _, filenames in os.walk(root):
        for filename in filenames:
            if keyword in filename:
                matching_files.append(os.path.join(dirpath, filename))

    return matching_files

def search_files(directory, keyword, num_threads=4):
    matching_files = []

    with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
        futures = []
        for root, _, _ in os.walk(directory):
            futures.append(executor.submit(search_files_in_directory, root, keyword))

        for future in concurrent.futures.as_completed(futures):
            matching_files.extend(future.result())

    return matching_files

def main():
    if len(sys.argv) != 3:
        print("Usage: python script.py <directory_to_search> <file_keyword>")
        return

    directory_to_search = sys.argv[1]
    file_keyword = sys.argv[2]

    result = search_files(directory_to_search, file_keyword)

    if result:
        print("Matching files found:")
        for file_path in result:
            print(file_path)
    else:
        print("No matching files found.")

if __name__ == "__main__":
    main()

このコードは、concurrent.futuresモジュールを使用してマルチスレッドを実現し、複数のディレクトリを同時に検索することで処理を高速化しています。num_threads変数を調整することで、同時に実行するスレッドの数を制御できます。ただし、同時実行スレッド数を多くしすぎると、システムの負荷が増える可能性があるため、適切な値を選択してください。

さらに高度な並列化#

さらに高度な並行処理を実現するためには、Pythonのasyncioライブラリを使用する方法があります。 asyncioを使用することで非同期のイベント駆動型プログラミングを行い、I/Oバウンドな操作を効率的に処理することができます。 以下は、asyncioを使用してファイル検索を並行処理する例です。

import os
import sys
import asyncio

async def search_files_in_directory(root, keyword):
    matching_files = []

    for dirpath, _, filenames in os.walk(root):
        for filename in filenames:
            if keyword in filename:
                matching_files.append(os.path.join(dirpath, filename))

    return matching_files

async def search_files(directory, keyword):
    matching_files = []
    tasks = []

    for root, _, _ in os.walk(directory):
        task = asyncio.create_task(search_files_in_directory(root, keyword))
        tasks.append(task)

    for task in asyncio.as_completed(tasks):
        matching_files.extend(await task)

    return matching_files

def main():
    if len(sys.argv) != 3:
        print("Usage: python script.py <directory_to_search> <file_keyword>")
        return

    directory_to_search = sys.argv[1]
    file_keyword = sys.argv[2]

    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(search_files(directory_to_search, file_keyword))

    if result:
        print("Matching files found:")
        for file_path in result:
            print(file_path)
    else:
        print("No matching files found.")

if __name__ == "__main__":
    main()
このコードでは、asyncioを使用して非同期な並行処理を行い、複数のディレクトリ内で同時にファイル検索を行います。 async defキーワードを使用して非同期関数を定義し、awaitキーワードを使用して非同期処理の完了を待機します。

正規表現を使用#

import os
import sys
import asyncio
import re

async def search_files_in_directory(root, keyword):
    matching_files = []

    for dirpath, _, filenames in os.walk(root):
        for filename in filenames:
            if re.search(keyword, filename):
                matching_files.append(os.path.join(dirpath, filename))

    return matching_files

async def search_files(directory, keyword):
    matching_files = []
    tasks = []

    for root, _, _ in os.walk(directory):
        task = asyncio.create_task(search_files_in_directory(root, keyword))
        tasks.append(task)

    for task in asyncio.as_completed(tasks):
        matching_files.extend(await task)

    return matching_files

def main():
    if len(sys.argv) != 3:
        print("Usage: python script.py <directory_to_search> <file_keyword>")
        return

    directory_to_search = sys.argv[1]
    file_keyword = sys.argv[2]

    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(search_files(directory_to_search, file_keyword))

    if result:
        print("Matching files found:")
        for file_path in result:
            print(file_path)
    else:
        print("No matching files found.")

if __name__ == "__main__":
    main()
python script.py /path/to/search "regex_pattern"

ファイルの内容から検索#

os.walk で検索#

Pythonを使用して、特定のディレクトリ内のファイルから特定の文字列を含むファイルを検索するプログラムを作成できます。

import os
import sys

def search_files(root_dir, search_string):
    for root, dirs, files in os.walk(root_dir):
        for file in files:
            file_path = os.path.join(root, file)
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                    if search_string in content:
                        print("Found in:", file_path)
            except Exception as e:
                print("Error:", e)

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: python script.py /path/to/directory 検索する文字列")
        sys.exit(1)

    root_directory = sys.argv[1]
    search_string = sys.argv[2]

    search_files(root_directory, search_string)
python script.py /path/to/directory "検索する文字列"

ここで、"/path/to/directory"を検索したいディレクトリのパスに置き換え、"検索する文字列"を実際に検索したい文字列に置き換えます。

高速化#

Pythonのスクリプトを高速化するために、マルチスレッドやマルチプロセスを使用することで、ファイルの検索処理を並列化する方法があります。 以下に、マルチスレッドを使用した高速化の例を示します

import os
import concurrent.futures
import sys

def search_in_file(file_path, search_string):
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
            if search_string in content:
                return file_path
    except Exception as e:
        print("Error:", e)
        return None

def search_files_in_directory(root_dir, search_string):
    found_files = []

    with concurrent.futures.ThreadPoolExecutor() as executor:
        for root, dirs, files in os.walk(root_dir):
            for file in files:
                file_path = os.path.join(root, file)
                future = executor.submit(search_in_file, file_path, search_string)
                found_files.append(future)

    return [future.result() for future in found_files if future.result() is not None]

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: python script.py root_directory search_string")
        sys.exit(1)

    root_directory = sys.argv[1]
    search_string = sys.argv[2]

    found_files = search_files_in_directory(root_directory, search_string)

    for file_path in found_files:
        print("Found in:", file_path)
python script.py /path/to/directory "検索する文字列"

上記のコードでは、concurrent.futures.ThreadPoolExecutorを使用してマルチスレッドでファイルの検索を行っています。 これにより、複数のファイルを同時に処理することができ、検索処理の高速化が期待できます。 ただし、マルチスレッドの利用には注意が必要であり、特にファイルの書き込みなどの共有リソースに対する同期が必要な場合は適切な対策が必要です。

さらに高度な高速化を追求する場合は、マルチプロセスを使用する方法も検討できますが、マルチプロセスの場合はプロセス間のデータ共有や同期がさらに複雑になることに注意してください。

高度な並列処理#

import os
import sys
import asyncio

async def search_keyword_in_file(file_path, keyword):
    matching_lines = []

    try:
        with open(file_path, "r", encoding="utf-8") as file:
            for line_number, line in enumerate(file, start=1):
                if keyword in line:
                    matching_lines.append((line_number, line))
    except Exception as e:
        print(f"Error while reading {file_path}: {e}")

    return matching_lines

async def search_files(directory, keyword):
    matching_lines = []
    tasks = []

    for root, _, files in os.walk(directory):
        for file in files:
            file_path = os.path.join(root, file)
            task = asyncio.create_task(search_keyword_in_file(file_path, keyword))
            tasks.append(task)

    for task in asyncio.as_completed(tasks):
        matching_lines.extend(await task)

    return matching_lines

def main():
    if len(sys.argv) != 3:
        print("Usage: python script.py <directory_to_search> <file_keyword>")
        return

    directory_to_search = sys.argv[1]
    file_keyword = sys.argv[2]

    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(search_files(directory_to_search, file_keyword))

    if result:
        print("Matching lines found:")
        for line_number, line in result:
            print(f"File: {line_number}: {line.strip()}")
    else:
        print("No matching lines found.")

if __name__ == "__main__":
    main()

上記のコードでは、search_keyword_in_file関数を使用してファイルの中身を検索し、一致した行を記録します。search_files関数はファイルの中身を検索するタスクを非同期に起動し、結果を収集します。 最終的に、一致した行の情報を表示します。

正規表現の使用#

正規表現を使用してファイルの中身を検索するコード例を以下に示します。正規表現を使用することで、より柔軟なパターンの検索が可能になります。

import os
import sys
import asyncio
import re

async def search_regex_in_file(file_path, pattern):
    matching_lines = []

    try:
        with open(file_path, "r", encoding="utf-8") as file:
            for line_number, line in enumerate(file, start=1):
                if re.search(pattern, line):
                    matching_lines.append((line_number, line))
    except Exception as e:
        print(f"Error while reading {file_path}: {e}")

    return matching_lines

async def search_files(directory, pattern):
    matching_lines = []
    tasks = []

    for root, _, files in os.walk(directory):
        for file in files:
            file_path = os.path.join(root, file)
            task = asyncio.create_task(search_regex_in_file(file_path, pattern))
            tasks.append(task)

    for task in asyncio.as_completed(tasks):
        matching_lines.extend(await task)

    return matching_lines

def main():
    if len(sys.argv) != 3:
        print("Usage: python script.py <directory_to_search> <regex_pattern>")
        return

    directory_to_search = sys.argv[1]
    regex_pattern = sys.argv[2]

    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(search_files(directory_to_search, regex_pattern))

    if result:
        print("Matching lines found:")
        for line_number, line in result:
            print(f"File: {line_number}: {line.strip()}")
    else:
        print("No matching lines found.")

if __name__ == "__main__":
    main()

このコードでは、正規表現を使用してファイルの中身を検索するために、re.search()関数を利用しています。コマンドライン引数として正規表現パターンを指定することで、複雑なテキストパターンを検索することができます。

コマンドラインから実行する際には、引数としてディレクトリと正規表現パターンを指定してください。

python script.py /path/to/search "regex_pattern"

このコードを使用することで、正規表現を活用してファイル内の特定のテキストパターンを効率的に検索することができます。