Front Matter 추가
스크립트
import os
import datetime
import re
import yaml
# 메타데이터 템플릿
metadata_template = {
"title": "{title}",
"weight": 10,
"categories": [],
"tags": [],
"toc": True,
"sidebar": {
"collapsed": True,
},
"cascade": {
"type": "docs",
}
}
# YAML 로드 및 덤프 도우미 함수
def load_yaml(content):
return yaml.safe_load(content)
def dump_yaml(metadata):
return yaml.dump(metadata, sort_keys=False, default_flow_style=False, allow_unicode=True)
# 파일 경로로부터 카테고리와 태그를 추출하는 함수
def extract_categories_and_tags(file_path, base_dir):
# base_dir을 기준으로 상대 경로를 얻음
relative_path = os.path.relpath(file_path, base_dir)
# 상대 경로를 분할하여 폴더 구조를 얻음
parts = relative_path.split(os.sep)
# 최상위 폴더를 카테고리로 설정
category = parts[0]
# 모든 상위 폴더를 태그로 설정
tags = parts[:-1] # 파일 이름을 제외한 모든 폴더
return category, tags
# 메타데이터를 업데이트하거나 추가하는 함수
def update_metadata(content, title, category, tags):
new_metadata = metadata_template.copy()
new_metadata["title"] = title
new_metadata["categories"] = [category]
new_metadata["tags"] = tags
# 기존 메타데이터가 있는지 확인
metadata_match = re.match(r"---(.*?)---", content, re.DOTALL)
if metadata_match:
existing_metadata_str = metadata_match.group(1)
existing_metadata = load_yaml(existing_metadata_str)
original_metadata = existing_metadata.copy() # 변경 전 메타데이터를 저장
# 필요한 필드가 없으면 추가, 있으면 유지
for key, value in metadata_template.items():
if key not in existing_metadata:
existing_metadata[key] = value
elif isinstance(value, dict):
for subkey, subvalue in value.items():
if subkey not in existing_metadata[key]:
existing_metadata[key][subkey] = subvalue
if existing_metadata != original_metadata: # 다른 메타데이터가 변경된 경우에만 업데이트
# 새로운 메타데이터 YAML 생성
updated_metadata_str = dump_yaml(existing_metadata)
new_metadata_block = f"---\n{updated_metadata_str}---\n"
return content.replace(metadata_match.group(0), new_metadata_block).replace('\n\n', '\n'), 'updated'
else:
return content, 'unchanged'
else:
# 메타데이터가 없는 경우 새 메타데이터 추가
new_metadata_str = dump_yaml(new_metadata)
new_metadata_block = f"---\n{new_metadata_str}---\n"
return new_metadata_block + content.lstrip(), 'added'
# 특정 디렉토리 내의 모든 파일에 메타데이터 추가 또는 업데이트
def add_metadata_to_files(directory):
total_files_count = 0
updated_count = 0
ignored_count = 0
added_count = 0
for root, dirs, files in os.walk(directory):
dirs[:] = [d for d in dirs if not d.startswith('.') and not d.startswith('_')]
for file in files:
if file.endswith('.md') and file != "_index.md":
total_files_count += 1
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# 파일 이름을 제목으로 사용 (확장자 제외)
title = os.path.splitext(file)[0]
# 카테고리와 태그 추출
category, tags = extract_categories_and_tags(file_path, directory)
updated_content, status = update_metadata(content, title, category, tags)
if status == 'updated':
updated_count += 1
elif status == 'added':
added_count += 1
if status in ('updated', 'added'):
try:
with open(file_path, 'w', encoding='utf-8') as f:
f.write(updated_content)
print(f"Updated metadata in {file_path}")
except Exception as e:
print(f"Error writing to {file_path}: {e}")
except Exception as e:
print(f"Error reading {file_path}: {e}")
ignored_count += 1
return total_files_count, updated_count, ignored_count, added_count
# 디렉토리 경로를 설정하세요
source_dir = os.environ.get('SOURCE_DIR', r"D:\obsidian")
print(f"Add Metadata start")
total_files_count, updated_count, ignored_count, added_count = add_metadata_to_files(source_dir)
# 로그 출력
print()
print(f"Total files processed: {total_files_count}")
print(f"Metadata updated: {updated_count}")
print(f"Metadata ignored: {ignored_count}")
print(f"Metadata added: {added_count}")
print(f"Add Metadata end")
print()
기능
메타데이터 템플릿 정의
- 기본 메타데이터 템플릿을 설정하여 파일에 추가할 메타데이터의 기본 구조를 제공합니다.
- 이 템플릿에는
title
,weight
,categories
,tags
,toc
,sidebar
,cascade
가 포함됩니다.
파일 경로 기반 카테고리 및 태그 추출
- 각 파일의 경로를 기반으로 카테고리와 태그를 자동으로 추출합니다.
- 최상위 폴더를 카테고리로 사용하고, 모든 상위 폴더를 태그로 사용합니다.
메타데이터 업데이트 및 추가
- 기존 파일의 메타데이터를 읽고, 누락된 필드는 템플릿을 기반으로 추가합니다.
- 메타데이터가 없는 파일에는 새 메타데이터를 추가합니다.
- 메타데이터가 변경되거나 추가된 파일은 수정 후 저장됩니다.