#!/usr/bin/env python3 import argparse from pathlib import Path import sys from typing import List, Dict, Set def read_list_file(list_file: Path, case_sensitive: bool) -> (List[str], Dict[str, str]): """Read folder names from txt, trim, skip blanks/comments, keep leaf names, and build a normalization map.""" lines = list_file.read_text(encoding="utf-8").splitlines() names: List[str] = [] for raw in lines: s = raw.strip() if not s or s.startswith("#"): continue # Keep only the leaf name even if a path is provided leaf = Path(s).name names.append(leaf) norm = (lambda x: x) if case_sensitive else (lambda x: x.lower()) # Map normalized -> first original occurrence (for pretty reporting) norm_map: Dict[str, str] = {} for n in names: k = norm(n) if k not in norm_map: norm_map[k] = n # Return unique in original order by using the map’s values unique_original_order = list(norm_map.values()) return unique_original_order, norm_map def list_subdirs(base_dir: Path, case_sensitive: bool) -> (List[str], Dict[str, str]): """List immediate subdirectories and build normalization map.""" subdirs = [p.name for p in base_dir.iterdir() if p.is_dir()] norm = (lambda x: x) if case_sensitive else (lambda x: x.lower()) norm_map: Dict[str, str] = {} for n in subdirs: k = norm(n) if k not in norm_map: norm_map[k] = n unique_original_order = list(norm_map.values()) return unique_original_order, norm_map def main(): ap = argparse.ArgumentParser( description="Compare folder names from a text list with actual subfolders in a base directory." ) ap.add_argument("--base-dir", required=True, type=Path, help="Parent directory containing the subfolders.") ap.add_argument("--list-file", required=True, type=Path, help="Text file with one folder name per line (paths ok; leaf will be used).") ap.add_argument("--case-sensitive", action="store_true", help="Use case-sensitive comparison (default: case-insensitive).") ap.add_argument("--show-extra", action="store_true", help="Also show folders present on disk but not in the list.") args = ap.parse_args() if not args.base_dir.exists(): print(f"ERROR: Base directory not found: {args.base_dir}", file=sys.stderr) sys.exit(2) if not args.list_file.exists(): print(f"ERROR: List file not found: {args.list_file}", file=sys.stderr) sys.exit(2) # Read inputs txt_list, txt_norm_map = read_list_file(args.list_file, args.case_sensitive) fs_list, fs_norm_map = list_subdirs(args.base_dir, args.case_sensitive) norm = (lambda x: x) if args.case_sensitive else (lambda x: x.lower()) txt_set: Set[str] = {norm(n) for n in txt_list} fs_set: Set[str] = {norm(n) for n in fs_list} missing_norm = sorted(txt_set - fs_set) # listed in txt but missing on disk extra_norm = sorted(fs_set - txt_set) # present on disk but not in txt print(f"== Results for {args.base_dir} ==") print(f"Listed in TXT but MISSING on disk: {len(missing_norm)}") for k in missing_norm: print(f" - {txt_norm_map.get(k, k)}") if args.show_extra: print() print(f"Present on disk but NOT listed in TXT: {len(extra_norm)}") for k in extra_norm: print(f" - {fs_norm_map.get(k, k)}") # Exit code: 0 if perfect match; 1 if differences sys.exit(0 if (not missing_norm and (not args.show_extra or not extra_norm)) else 1) if __name__ == "__main__": main()