Created
October 1, 2024 10:55
-
-
Save alwashali/cf6eaf8eef9c0bb9ed5fe6d62e9e3f50 to your computer and use it in GitHub Desktop.
Delete images that was not referenced in any notes and move images to the note directory if it's referenced once
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import re | |
import shutil | |
import sys | |
class ObsidianFileManager: | |
def __init__(self, vault_path): | |
self.vault_path = vault_path | |
self.markdown_files = self.get_markdown_files() | |
self.files = self.get_all_files() | |
self.references = self.build_references() | |
def get_markdown_files(self): | |
md_files = [] | |
for root, _, files in os.walk(self.vault_path): | |
if '.obsidian' in root.split(os.sep): | |
continue | |
for file in files: | |
if file.endswith('.md') and not file.startswith('.'): | |
md_files.append(os.path.join(root, file)) | |
return md_files | |
def get_all_files(self): | |
all_files = set() | |
for root, _, files in os.walk(self.vault_path): | |
if '.obsidian' in root.split(os.sep): | |
continue | |
for file in files: | |
if not file.endswith('.md') and not file.startswith('.'): | |
all_files.add(os.path.join(root, file)) | |
return all_files | |
def extract_references(self, file_content): | |
return re.findall(r'!\[\[([^\|\]]+)', file_content) | |
def build_references(self): | |
ref_dict = {} | |
for md_file in self.markdown_files: | |
with open(md_file, 'r', encoding='utf-8') as f: | |
content = f.read() | |
refs = self.extract_references(content) | |
for ref in refs: | |
ref_path = self.find_file_in_vault(ref) | |
if ref_path: | |
if ref_path not in ref_dict: | |
ref_dict[ref_path] = [] | |
ref_dict[ref_path].append(md_file) | |
return ref_dict | |
def find_file_in_vault(self, ref): | |
for file_path in self.files: | |
if os.path.basename(file_path) == ref: | |
return file_path | |
return None | |
def get_orphan_files(self): | |
return [file for file in self.files if file not in self.references] | |
def get_singular_files(self): | |
return [file for file, refs in self.references.items() if len(refs) == 1] | |
def delete_orphans(self): | |
orphans = self.get_orphan_files() | |
for orphan in orphans: | |
os.remove(orphan) | |
def move_singular_files(self): | |
singular_files = self.get_singular_files() | |
for file in singular_files: | |
dest_folder = os.path.dirname(self.references[file][0]) | |
shutil.move(file, dest_folder) | |
def process_command(self, command): | |
if command == '--delete-orphans': | |
self.delete_orphans() | |
elif command == '--move-singular': | |
self.move_singular_files() | |
if __name__ == "__main__": | |
vault_path = sys.argv[1] | |
command = sys.argv[2] if len(sys.argv) > 2 else None | |
manager = ObsidianFileManager(vault_path) | |
if command: | |
manager.process_command(command) | |
else: | |
print("Orphan files:", manager.get_orphan_files()) | |
print("Singular files:", manager.get_singular_files()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment