Created
August 11, 2025 12:12
-
-
Save fabriziosalmi/2242c04956d148cf201cc484fe8dc609 to your computer and use it in GitHub Desktop.
index-all-bia
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 json | |
import argparse | |
import logging | |
from collections import defaultdict | |
from datetime import datetime | |
# --- CONFIGURAZIONE --- | |
# Percorso base da cui iniziare la scansione | |
BASE_PATH = "/mnt/user" | |
# Elenco delle directory di primo livello da escludere completamente | |
# Lo script controllerà se un percorso INIZIA con uno di questi. | |
EXCLUDE_DIRS = [ | |
"appdata", | |
"domains", | |
"isos", | |
"Backup_Appdata", | |
"system", | |
"TUTTO", | |
"MUSICA", | |
"AUDIOLIBRI", | |
] | |
# Nome del file JSON di output | |
JSON_FILE_NAME = "media_index.json" | |
# Prefisso per il file di testo di output | |
TXT_FILE_PREFIX = "index" | |
# -------------------- | |
def setup_logging(debug_mode: bool): | |
"""Configura il logging per l'applicazione.""" | |
level = logging.DEBUG if debug_mode else logging.INFO | |
logging.basicConfig( | |
level=level, | |
format="[%(asctime)s] [%(levelname)s] - %(message)s", | |
datefmt="%Y-%m-%d %H:%M:%S", | |
) | |
def index_media(base_path: str, exclude_dirs: list, follow_links: bool): | |
""" | |
Scansiona le directory, indicizza i file e restituisce una struttura dati. | |
La struttura è un dizionario { "percorso_cartella": ["file1", "file2", ...] }. | |
""" | |
media_index = defaultdict(list) | |
total_files_count = 0 | |
# Pre-calcola i percorsi completi da escludere per efficienza | |
full_exclude_paths = [os.path.join(base_path, d) for d in exclude_dirs] | |
logging.debug(f"Percorsi di esclusione completi: {full_exclude_paths}") | |
logging.info(f"Inizio scansione da '{base_path}'...") | |
logging.info(f"Seguire i link simbolici: {'Sì' if follow_links else 'No'}") | |
for root, dirs, files in os.walk(base_path, topdown=True, followlinks=follow_links): | |
# Escludi le directory specificate | |
# `topdown=True` permette di modificare `dirs` per potare l'albero di ricerca | |
if any(root.startswith(excluded_path) for excluded_path in full_exclude_paths): | |
logging.debug(f"Salto la directory esclusa e le sue sottodirectory: {root}") | |
dirs[:] = [] # Svuota la lista di sottodirectory per non visitarle | |
continue | |
if not files: | |
continue # Salta le cartelle che non contengono file | |
try: | |
# Aggiungiamo solo i file di questa directory all'indice | |
# I file vengono già ordinati per un output consistente | |
sorted_files = sorted(files) | |
media_index[root] = sorted_files | |
total_files_count += len(sorted_files) | |
# Log di progresso ogni 1000 cartelle indicizzate | |
if len(media_index) % 1000 == 0: | |
logging.info(f"Indicizzate {len(media_index)} cartelle e {total_files_count} file...") | |
except OSError as e: | |
logging.error(f"Errore di accesso durante la scansione di '{root}': {e}") | |
continue | |
logging.info(f"Scansione completata. Trovate {total_files_count} file in {len(media_index)} cartelle.") | |
return media_index | |
def save_json_index(index_data: dict, filename: str): | |
"""Salva l'indice in formato JSON.""" | |
logging.info(f"Salvataggio dell'indice JSON in '{filename}'...") | |
try: | |
with open(filename, "w", encoding="utf-8") as f: | |
json.dump(index_data, f, ensure_ascii=False, indent=2) | |
logging.info("Indice JSON salvato con successo.") | |
except IOError as e: | |
logging.error(f"Impossibile scrivere il file JSON '{filename}': {e}") | |
def save_txt_index(index_data: dict, filename_prefix: str): | |
"""Salva un report testuale formattato dell'indice.""" | |
date_str = datetime.now().strftime("%Y-%m-%d") | |
filename = f"{filename_prefix}_{date_str}.txt" | |
logging.info(f"Creazione del report testuale in '{filename}'...") | |
try: | |
with open(filename, "w", encoding="utf-8") as out: | |
# Ordina le cartelle per percorso per un output pulito | |
for folder, files in sorted(index_data.items()): | |
# Corregge il percorso per rimuovere il prefisso base se non è "/" | |
display_folder = folder | |
if BASE_PATH != "/" and folder.startswith(BASE_PATH): | |
display_folder = folder[len(BASE_PATH):] or "/" | |
out.write(f"📁 {display_folder}\n") | |
for file in files: # i file sono già ordinati | |
out.write(f" - {file}\n") | |
out.write("\n") | |
logging.info(f"Report testuale creato con successo con {len(index_data)} cartelle.") | |
except IOError as e: | |
logging.error(f"Impossibile scrivere il file TXT '{filename}': {e}") | |
def main(): | |
"""Funzione principale dello script.""" | |
parser = argparse.ArgumentParser( | |
description="Indicizzatore di file multimediali per Unraid.", | |
formatter_class=argparse.ArgumentDefaultsHelpFormatter | |
) | |
parser.add_argument( | |
"--debug", | |
action="store_true", | |
help="Abilita il logging di debug dettagliato." | |
) | |
parser.add_argument( | |
"--follow-links", | |
action="store_true", | |
help="Segue i collegamenti simbolici durante la scansione." | |
) | |
args = parser.parse_args() | |
setup_logging(args.debug) | |
# Esegui l'indicizzazione | |
media_index = index_media(BASE_PATH, EXCLUDE_DIRS, args.follow_links) | |
if not media_index: | |
logging.warning("Nessun file trovato. L'indice non verrà creato.") | |
return | |
# Salva gli output | |
save_json_index(media_index, JSON_FILE_NAME) | |
save_txt_index(media_index, TXT_FILE_PREFIX) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment