링크 형식 변경
스크립트
- change_link.py
import os
import re
import urllib.parse
def find_file_recursively(root_dir, search_dir, filename):
"""
파일을 검색합니다. 현재 디렉토리부터 시작하여 부모 디렉토리로 이동합니다.
"""
for dirpath, _, filenames in os.walk(search_dir):
if filename in filenames:
return os.path.join(dirpath, filename)
parent_dir = os.path.dirname(search_dir)
if parent_dir and parent_dir != root_dir:
return find_file_recursively(root_dir, parent_dir, filename)
return None
def read_file_with_fallback(file_path):
"""
파일을 열어 내용을 읽습니다. UTF-8 디코딩이 실패하면 latin-1로 시도합니다.
"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
return f.read()
except UnicodeDecodeError:
with open(file_path, 'r', encoding='latin-1') as f:
return f.read()
def convert_links_to_absolute(root_dir):
"""
옵시디언 링크와 Markdown 링크를 절대 경로로 변환합니다.
"""
log_changes = [] # 변경된 항목을 기록할 로그 리스트
image_extensions = {'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.tiff', '.svg'} # 이미지 확장자 목록
for dirpath, dirnames, filenames in os.walk(root_dir):
# . 또는 _로 시작하는 디렉토리 제외
dirnames[:] = [d for d in dirnames if not d.startswith('.') and not d.startswith('_')]
for filename in filenames:
# _index.md 파일은 제외
if filename == "_index.md":
continue
file_path = os.path.join(dirpath, filename)
# 파일 내용 읽기
content = read_file_with_fallback(file_path)
original_content = content
# 옵시디언 및 Markdown 링크 패턴 검색
obsidian_links = re.findall(r'\[\[([^\]]+)\]\]', content)
markdown_links = re.findall(r'\[([^\]]+)\]\(([^)]+)\)', content)
# 변경 로그를 저장하기 위한 리스트
file_log_changes = []
# 옵시디언 링크 변환
for link in obsidian_links:
# 이미지 확장자 제외
base_name = os.path.basename(link)
if os.path.splitext(base_name)[1].lower() in image_extensions:
continue
# .md 확장자 추가해 파일 찾기
if '.' not in base_name:
base_name += '.md'
# 파일을 현재 디렉토리부터 찾아서 가장 가까운 파일 사용
absolute_path = find_file_recursively(root_dir, dirpath, base_name)
if absolute_path:
# 절대 경로로 변환하고 .md 확장자 제거
root_relative_path = os.path.relpath(absolute_path, root_dir)
root_relative_path_no_ext = os.path.splitext(root_relative_path)[0]
# _index로 끝나는 링크는 변경하지 않음
if not root_relative_path_no_ext.endswith('_index'):
# 절대 경로 생성
new_link = f'[{link}](/' + root_relative_path_no_ext.replace('\\', '/') + ')'
if new_link != f'[{link}]({link})': # Avoid redundant replacement
content = content.replace(f'[[{link}]]', new_link)
# 변경 로그 추가
file_log_changes.append(f"Changed: [[{link}]] -> {new_link}")
# Markdown 링크 변환
for title, link in markdown_links:
# 공백 제거 및 파일명 얻기
base_name = os.path.basename(link)
if os.path.splitext(base_name)[1].lower() in image_extensions:
continue
# .md 확장자 추가해 파일 찾기
if '.' not in base_name:
base_name += '.md'
# 파일을 현재 디렉토리부터 찾아서 가장 가까운 파일 사용
absolute_path = find_file_recursively(root_dir, dirpath, base_name)
if absolute_path:
# 절대 경로로 변환하고 .md 확장자 제거
root_relative_path = os.path.relpath(absolute_path, root_dir)
root_relative_path_no_ext = os.path.splitext(root_relative_path)[0]
# _index로 끝나는 링크는 변경하지 않음
if not root_relative_path_no_ext.endswith('_index'):
# 절대 경로 생성
new_link = f'[{title}](/' + root_relative_path_no_ext.replace('\\', '/') + ')'
if new_link != f'[{title}]({link})': # Avoid redundant replacement
content = content.replace(f'[{title}]({link})', new_link)
# 변경 로그 추가
file_log_changes.append(f"\t\tChanged: [{title}]({link}) -> {new_link}")
# 파일 내용 업데이트
if original_content != content:
with open(file_path, 'w', encoding='utf-8', errors='ignore') as file:
file.write(content)
# 로그에 변경 사항 추가
log_changes.append(f"\tFile: {file_path}")
log_changes.extend(file_log_changes)
return log_changes
def main():
# 소스 디렉토리 설정
source_dir = os.environ.get('SOURCE_DIR', r"D:\obsidian")
# 옵시디언 및 Markdown 링크를 절대 경로로 변환
log_changes = convert_links_to_absolute(source_dir)
# 로그 출력
print("\nChanges link style start")
for log in log_changes:
print(log)
print("\nChanges link style end")
if __name__ == "__main__":
main()
기능
파일 검색
- 상대 경로 링크에 대해 현재 디렉토리부터 상위 디렉토리로 이동하며 해당 파일을 찾습니다.
- 이를 통해 링크된 파일을 프로젝트 내에서 가장 가까운 위치에서 찾을 수 있습니다.
파일 읽기
- UTF-8로 파일을 읽고, 실패할 경우
latin-1
인코딩으로 시도합니다.
Obsidian 및 Markdown 링크 변환
- 디렉토리를 순회하며, Obsidian 링크(
[[링크]]
)와 Markdown 링크([제목](링크)
)를 절대 경로로 변환합니다. - 이미지 파일은 링크 변환에서 제외됩니다.
- 링크를 절대 경로로 변환할 때
.md
확장자는 제거되며,_index
로 끝나는 링크는 변경되지 않습니다.