Last active
July 31, 2025 17:07
-
-
Save mao-odoo/7d02339595107d353e809aa57255049c to your computer and use it in GitHub Desktop.
search filestore for orphaned files (deleted from ir.attachments)
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
| #!/usr/bin/env python3 | |
| import sys | |
| import os | |
| import time | |
| import psycopg2 | |
| def walk_filestore(filestore_path): | |
| for root, dirs, files in os.walk(filestore_path): | |
| if "checklist" not in root.split("/")[-2:] and files: | |
| for file in files: | |
| assert root.split("/")[-1] == file[:2], f"files in abnormal location in filestore: {root} - {file}" | |
| yield root, file | |
| def is_file_orphan(sql_cr, file_name): | |
| # true if file does not exist on the database anymore | |
| sql_cr.execute("SELECT count(id) from ir_attachment where checksum = %s", (file_name, )) | |
| nbr = sql_cr.fetchone()[0] | |
| return nbr == 0 | |
| def delete_file(file_path): | |
| print(f"deleting --> {file_path}") | |
| assert os.path.isfile(file_path), f"not a file, something is weird with {file_path}" | |
| os.remove(file_path) | |
| pass | |
| def delete_orphans(filestore_path, dbname, dry_run=True): | |
| if not dry_run: | |
| print("this will delete stuff, starting in 5 seconds") | |
| time.sleep(6) | |
| print("ok, let's go") | |
| orphans, ok = 0, 0 | |
| with psycopg2.connect(database=dbname) as cnx, cnx.cursor() as cr: | |
| for dir_path, file_name in walk_filestore(filestore_path): | |
| # print(dir_path, file_name) | |
| if is_file_orphan(cr, file_name): | |
| orphans += 1 | |
| # print(f"nuke file {file_name}") | |
| if not dry_run: | |
| delete_file(f"{dir_path}/{file_name}") | |
| else: | |
| ok += 1 | |
| print(f"orphans count: {orphans}") | |
| print(f"regular files count: {ok}") | |
| if __name__ == "__main__": | |
| argv = sys.argv | |
| if "--help" in argv or len(argv) < 3: | |
| print("filestore_search_ophanes.py dbname filestore_location [--for-real]") | |
| else: | |
| delete_orphans(argv[2], argv[1], "--for-real" not in argv) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment