Skip to content

Instantly share code, notes, and snippets.

@takuya-andou
Created March 15, 2024 10:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takuya-andou/b0f808f113a82f63e91ead5bfc023a21 to your computer and use it in GitHub Desktop.
Save takuya-andou/b0f808f113a82f63e91ead5bfc023a21 to your computer and use it in GitHub Desktop.
カレントディレクトリ以下のすべてのファイルの内容を1つの大きなテキストファイルにまとめるためのものです。
# 作者: t_andou
#
# このスクリプトは、カレントディレクトリ以下のすべてのファイルの内容を再帰的に読み込み、
# 1つの大きなテキストファイルにまとめるためのものです。
#
# 使い方:
# 1. このスクリプトをプロジェクトのルートディレクトリに配置します。
# 2. コマンドラインから `python merge_all.py` を実行します。
# (merge_all.py は実際のスクリプトファイル名に置き換えてください)
# 3. スクリプトが実行されると、カレントディレクトリ以下のすべてのファイルの内容が
# 1つまたは複数の output*.txt ファイルにまとめられます。
# 各出力ファイルのサイズは最大10MBに制限されます。
#
# 除外ルール:
# - 隠しファイルとディレクトリ (ドット . で始まるもの) は除外されます。
# - .gitignore と .mergeignore に記載されているパターンにマッチするファイルとディレクトリは除外されます。
# - このスクリプト自体も除外されます。
#
# 出力形式:
# - 各ファイルの内容は、ファイルの相対パスと内容を示すマークダウン形式で出力されます。
# - ファイルの相対パスは1行目に記載されます。
# - ファイルの内容はコードブロック (```) 内に記載されます。
# - ファイル間は2つの空行で区切られます。
import os
import fnmatch
def get_file_contents(file_path):
with open(file_path, 'r', errors='ignore') as file:
return file.read()
def write_to_file(file_path, content):
with open(file_path, 'w') as file:
file.write(content)
def is_hidden(path):
return path.startswith('.')
def should_exclude(file_path, exclude_patterns):
for pattern in exclude_patterns:
if pattern.endswith('/'):
if fnmatch.fnmatch(file_path, pattern[:-1]) or file_path.startswith(pattern[:-1]):
return True
else:
if fnmatch.fnmatch(file_path, pattern):
return True
return False
def should_exclude_directory(dir_path, exclude_patterns):
for pattern in exclude_patterns:
if fnmatch.fnmatch(dir_path, pattern) or dir_path.startswith(pattern):
return True
return False
def main():
output_file_prefix = 'output'
output_file_extension = '.txt'
max_file_size = 10 * 1024 * 1024 # 10MB
current_file_size = 0
current_file_index = 1
current_file_content = ''
script_file = os.path.basename(__file__)
exclude_patterns = [script_file]
for ignore_file in ['.gitignore', '.mergeignore']:
if os.path.exists(ignore_file):
with open(ignore_file, 'r') as file:
exclude_patterns.extend(file.read().splitlines())
for root, dirs, files in os.walk('.'):
dirs[:] = [d for d in dirs if not is_hidden(d)]
# 除外ルールに基づいてディレクトリをスキップ
dirs[:] = [d for d in dirs if not should_exclude_directory(os.path.join(root, d), exclude_patterns)]
for file in files:
if is_hidden(file):
continue
file_path = os.path.join(root, file)
relative_path = os.path.relpath(file_path)
if should_exclude(relative_path, exclude_patterns):
continue
file_content = get_file_contents(file_path)
content_to_add = f'{relative_path}\n```\n{file_content}\n```\n\n'
content_size = len(content_to_add.encode('utf-8'))
if current_file_size + content_size > max_file_size:
output_file_name = f'{output_file_prefix}{current_file_index}{output_file_extension}'
write_to_file(output_file_name, current_file_content)
current_file_index += 1
current_file_size = 0
current_file_content = ''
current_file_content += content_to_add
current_file_size += content_size
if current_file_content:
output_file_name = f'{output_file_prefix}{current_file_index}{output_file_extension}'
write_to_file(output_file_name, current_file_content)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment