Skip to content

Instantly share code, notes, and snippets.

@alwashali
Created October 1, 2024 10:55
Show Gist options
  • Save alwashali/cf6eaf8eef9c0bb9ed5fe6d62e9e3f50 to your computer and use it in GitHub Desktop.
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
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