#!/usr/bin/env python3 """ Move all folders from UH/ into the gdrive root, then delete the empty UH folder. Uses rclone connection-string syntax to treat UH as a separate root. """ import json, subprocess, sys UH_ID = "1fEOd5m5psVYeN0hK6G_UJx_XwmXZcZ6l" UH_SRC = f"gdrive,root_folder_id={UH_ID}:" # UH as remote root ROOT = "gdrive:" def run(*args, check=False): cmd = list(args) print(f" $ {' '.join(cmd)}") r = subprocess.run(cmd, capture_output=True, text=True) if r.returncode != 0: print(f" ERROR: {r.stderr.strip() or r.stdout.strip()}") else: if r.stdout.strip(): print(f" {r.stdout.strip()[:120]}") return r.returncode == 0 # List top-level dirs in UH print("Listing UH top-level folders...") r = subprocess.run( ["rclone", "lsjson", UH_SRC, "--max-depth", "0"], capture_output=True, text=True ) items = json.loads(r.stdout) folders = [f["Name"] for f in items if f["IsDir"]] files = [f["Name"] for f in items if not f["IsDir"]] if files: print(f"\nWARNING: {len(files)} loose files in UH root (not in a subfolder):") for f in files: print(f" {f}") print(f"\nFolders to move: {folders}\n") print("=== Moving folders from UH → root ===\n") ok = err = 0 for folder in folders: src = f"{UH_SRC}{folder}" dst = f"{ROOT}{folder}" print(f"Moving {folder}/ → root/{folder}/") if run("rclone", "move", src, dst, "--delete-empty-src-dirs"): ok += 1 else: err += 1 print(f"\nMoves done: {ok} ok, {err} errors") if err: print("There were errors — NOT deleting UH. Fix errors first.") sys.exit(1) # Verify UH is now empty print("\nVerifying UH is empty...") r = subprocess.run( ["rclone", "lsjson", UH_SRC, "--recursive"], capture_output=True, text=True ) remaining = json.loads(r.stdout) remaining = [f for f in remaining if not f["IsDir"]] if remaining: print(f"WARNING: {len(remaining)} files still in UH — NOT deleting:") for f in remaining: print(f" {f['Path']}") sys.exit(1) print("UH is empty. Deleting...") if run("rclone", "purge", f"{ROOT}UH"): print("\n✅ UH folder deleted successfully.") else: print("\n⚠️ Could not delete UH — you may need to remove it manually.")