Pythonでパッケージ作成プログラムを作成

業務でプログラムのパッチを抜き出す度に時間がかかっていたのでパッケージ作成プログラムを自作した。

仕様
１．検索対象のフォルダを設定
２．特定のキーワードを設定する。(2021-00001など)
３．検索結果用のフォルダを作成する。
４．２で設定したフォルダ内を１のキーワードで再帰的にgrep検索を行う。
５．ファイルが見つかった場合、３のフォルダ下に２のフォルダと同様の階層フォルダを作成し検索して見つかったファイルを格納していく

```python

# -*- coding: utf-8 -*-
#make package tool

import os
import re
import shutil
import codecs

from chardet.universaldetector import UniversalDetector

walk_subdirs = True
file_count = 0

#set directory path to search
print("検索対象のディレクトリを入力してください。")
search_dir = input('>> ')

#set package_id to search
print("検索対象のIDを入力してください。")
search_pattern = input('>> ')

#set directory to make output search result 
print("作成先のディレクトリを入力してください。")
make_dir = input('>> ')

#specify file format
ext_patterns = (
    ".java",
    ".xml",
    ".cpp",
    ".hpp",
    ".c",
    ".h",
    ".rc",
    ".rh",
    ".bat",
    ".cmd",
)

# ファイルをエンコードする。
def detect_encoding(file_path):
    detector = UniversalDetector()
    try:
        with open(file_path, mode = 'rb') as f:
            while True:
                data = f.readline()
                if data == b'':
                    break

                detector.feed(data)
                if detector.done:
                    break
    finally:       detector.close()

    detected_encodings = detector.result

    return detected_encodings["encoding"]

# ファイルを再帰的にgrepする。
def search_files(dir_path, file_name_list):
    matched_list = []
    for file_name in file_name_list:
        global file_count
        file_count = file_count + 1
        _, ext = os.path.splitext(file_name)
        if not ext in ext_patterns:
            continue

        file_path = os.path.join(dir_path, file_name)

        #本来だとしなければならないが時間短縮のためにコメントアウト
#       encoding = detect_encoding(file_path)

#       with open(file_path, encoding=encoding) as f:
        #urf8 でエンコード形式を固定しているため何か不具合あったら元に戻す予定
        with codecs.open(file_path, 'r', 'utf8', 'ignore') as f:
            line_number = 1
            for line in f:
                m = re.search(search_pattern, line)
                if m:
                    file_info = {
                        "path": file_path,
                        "line_number": line_number,
                        "line": line.strip(),
                        "dir": dir_path
                    }
                    matched_list.append(file_info)
                    break
                line_number = line_number + 1
    return matched_list

def print_matched_list(matched_list):
    for file_info in matched_list:

        # コピー対象先のディレクトリを設定
        target_dir = make_dir + "\\" + search_pattern + "\\" + file_info["dir"].replace(search_dir,"")
        # コピー対象のファイル名を取得
        target_file_name = target_dir + file_info["path"].replace( file_info["dir"], "")
        if os.path.exists(target_dir) == False:
            try:
                # コピー対象先のディレクトリを作成。
                os.makedirs(target_dir)
            except FileExistsError:
                # 既に存在する場合は何もしない。
                pass

        # コピー対象のファイルが存在するかチェックを行い存在しない場合のみコピーを行う。
        if os.path.exists(target_dir + target_file_name) == False:
            shutil.copy(file_info["path"], target_dir)

if walk_subdirs:
    matched_list = []
    for root, dirs, files in os.walk(search_dir):
        sub_matched_list = search_files(root, files)
        matched_list.extend(sub_matched_list)
else:
    file_name_list = os.listdir(search_dir)
    matched_list = search_files(search_dir, file_name_list)

print_matched_list(matched_list)
print("パッケージ作成完了")

```