옵시디언 파일 중 옵션에 따른 업로드 파일 설정

연결 문서

옵시디언 파일 중 옵션에 따른 업로드 파일 설정

  • 원본 폴더 : 옵시디언 루트 디렉토리
  • 복사 폴더 : 블로그 폴더로 절대 경로로 _post 를 가르키면 됨

import os
import yaml
import re
import shutil
from datetime import datetime

def get_md_files_with_blog_true(folder_path):
    md_files_with_metadata = []

    for root, dirs, files in os.walk(folder_path):
        for file in files:
            if file.endswith('.md'):
                full_path = os.path.join(root, file)
                with open(full_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                    # YAML 프론트 매터 추출 (정규표현식 사용)
                    yaml_match = re.match(r'^---\s*\n(.*?)\n---\s*\n?', content, re.DOTALL)
                    if yaml_match:
                        yaml_content = yaml_match.group(1)
                        try:
                            metadata = yaml.safe_load(yaml_content)
                            # metadata가 딕셔너리인지 확인
                            if isinstance(metadata, dict) and 'blog' in metadata and metadata['blog'] == True:
                                md_files_with_metadata.append((full_path, metadata, content))
                        except yaml.YAMLError as e:
                            print(f"YAML 파싱 오류 ({full_path}): {e}")
    return md_files_with_metadata

def generate_destination_path(md_file, metadata, folder_path, destination_base):
    # 원본 폴더로부터의 상대 경로 계산
    relative_path = os.path.relpath(md_file, folder_path)
    # 파일 이름과 디렉토리 분리
    relative_dir, original_filename = os.path.split(relative_path)
    # 파일명과 확장자 분리
    filename_without_ext, ext = os.path.splitext(original_filename)
    # 파일 이름의 띄어쓰기를 '-'로 대체
    modified_filename = filename_without_ext.replace(' ', '-')
    # create_date 추출 및 날짜 부분만 사용
    if 'create_date' in metadata:
        # 날짜 부분만 추출 (YYYY-MM-DD)
        create_date_str = str(metadata['create_date'])
        try:
            # create_date가 datetime 형식이 아닌 문자열일 수 있으므로 파싱 시도
            create_date = datetime.strptime(create_date_str, '%Y-%m-%d %H:%M')
        except ValueError:
            try:
                create_date = datetime.strptime(create_date_str, '%Y-%m-%d')
            except ValueError:
                print(f"날짜 형식 오류 ({md_file}): {create_date_str}")
                return None
        date_prefix = create_date.strftime('%Y-%m-%d')
    else:
        print(f"create_date 없음 ({md_file})")
        return None
    # 새로운 파일 이름 생성
    new_filename = f"{date_prefix}-{modified_filename}{ext}"
    # 새로운 상대 경로 생성
    new_relative_path = os.path.join(relative_dir, new_filename)
    # 대상 파일의 전체 경로 생성
    destination_path = os.path.join(destination_base, new_relative_path)
    return destination_path

def synchronize_folders(folder_path, destination_base):
    # 원본 폴더의 파일 목록 가져오기
    md_files_with_metadata = get_md_files_with_blog_true(folder_path)

    # 복사 폴더의 기존 파일 목록 가져오기
    existing_files_in_destination = []
    for root, dirs, files in os.walk(destination_base):
        for file in files:
            if file.endswith('.md'):
                existing_files_in_destination.append(os.path.join(root, file))

    # 원본 파일의 대상 경로 매핑 생성 (원본 파일 경로: (대상 파일 경로, 메타데이터, 내용))
    source_to_destination = {}
    # 링크 매핑 생성 (파일 제목: URL)
    title_to_url = {}
    for md_file, metadata, original_content in md_files_with_metadata:
        destination_path = generate_destination_path(md_file, metadata, folder_path, destination_base)
        if destination_path:
            source_to_destination[md_file] = (destination_path, metadata, original_content)
            # 파일 제목에서 띄어쓰기를 '-'로 대체하여 URL 생성
            if 'title' in metadata:
                title = metadata['title']
                url_title = title.replace(' ', '-')
                # URL 생성 (도메인 이름은 필요에 따라 변경하세요)
                url = f"https://chanp5660.github.io/{url_title}"
                title_to_url[title] = url

    # 대상 파일의 원본 파일 경로 목록
    destination_files = [dest_path for dest_path, _, _ in source_to_destination.values()]

    # 복사 폴더에서 원본에 없는 파일 삭제
    for existing_file in existing_files_in_destination:
        if existing_file not in destination_files:
            os.remove(existing_file)
            print(f"삭제됨: {existing_file}")

    # 파일 복사 및 업데이트
    for md_file, (destination_path, metadata, original_content) in source_to_destination.items():
        # 대상 디렉토리가 존재하지 않으면 생성
        destination_dir = os.path.dirname(destination_path)
        if not os.path.exists(destination_dir):
            os.makedirs(destination_dir)
        # 파일이 없거나 원본이 더 최신이면 복사
        if (not os.path.exists(destination_path)) or (os.path.getmtime(md_file) > os.path.getmtime(destination_path)):
            # YAML 프론트 매터 수정
            # 'tags'를 'categories'로 변경
            if 'tags' in metadata:
                metadata['categories'] = metadata.pop('tags')
            # 'mathjax: true'와 'layout: post' 추가
            metadata['mathjax'] = True
            metadata['layout'] = 'post'
            # 수정된 YAML 프론트 매터를 문자열로 변환
            new_yaml_content = yaml.dump(metadata, allow_unicode=True, sort_keys=False)
            # YAML 프론트 매터 재구성
            new_front_matter = f"---\n{new_yaml_content}---\n"
            # 원본 내용에서 기존 YAML 프론트 매터를 수정된 것으로 대체
            new_content = re.sub(r'^---\s*\n(.*?)\n---\s*\n?', new_front_matter, original_content, flags=re.DOTALL)
            # 내용 중 링크 변경
            # 패턴: [[파일 제목]] (단, [[#파일 제목]]은 제외)
            def replace_link(match):
                full_match = match.group(0)
                link_text = match.group(1)
                if link_text.startswith('#'):
                    # [[#파일 제목]] 형태는 변경하지 않음
                    return full_match
                else:
                    # 링크 텍스트에서 앞뒤 공백 제거
                    link_text = link_text.strip()
                    if link_text in title_to_url:
                        url = title_to_url[link_text]
                        return f"[{link_text}]({url})"
                    else:
                        return full_match  # 매핑이 없으면 변경하지 않음

            new_content = re.sub(r'\[\[([^\[\]]+)\]\]', replace_link, new_content)
            # 수정된 내용을 대상으로 파일에 작성
            with open(destination_path, 'w', encoding='utf-8') as f:
                f.write(new_content)
            print(f"복사 및 내용 수정 완료: {md_file} -> {destination_path}")
        else:
            #print(f"최신 상태 유지: {destination_path}")
            continue

# 실행 부분
folder_path = '원본 폴더 경로'  # 원본 폴더 경로로 변경하세요.
destination_base = '복사 폴더 경로'  # 복사 폴더 경로로 변경하세요.

synchronize_folders(folder_path, destination_base)




    Enjoy Reading This Article?

    Here are some more articles you might like to read next:

  • 옵시디언에서 일정 관리
  • LangChain Expression Language(LCEL)
  • 우도(likelihood)
  • python 에서 데코레이터
  • 특정 커밋으로 돌아가는 방법