ARTICLE AD BOX
I wish to migrate a folder tree structure from one Windows PC to another by running a python script on the destination PC. Here is the code I am using:
import shutil import os import sys import logging import subprocess from datetime import datetime from pathlib import Path # ======================= # CONFIGURATION # ======================= # UNC root of source machine (example: r"\\OLD-PC\C$") # SOURCE_ROOT = r"D$ SOURCE_ROOT = Path("D:\\") # Local destination root (almost always C:\) # DEST_ROOT = r"C:\\" DEST_ROOT = Path("C:\\") # Folders to migrate (absolute paths from source C:\) FOLDERS_TO_MIGRATE = [ r"dgarrard", r"PNC", r"Installers", r"Nufocus", r"openssl", r"win-acme", r"ProgramData\win-acme", r"Program Files\Inkscape", r"MYPROGRAMS\wkhtmltopdf" ] # Log file LOG_FILE = rf"C:\migration_log_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log" # ======================= # LOGGING SETUP # ======================= logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s", handlers=[ logging.FileHandler(LOG_FILE, encoding="utf-8"), logging.StreamHandler(sys.stdout) ] ) # ======================= # FUNCTIONS # ======================= def ensure_admin(): import ctypes if not ctypes.windll.shell32.IsUserAnAdmin(): print("❌ This script must be run as Administrator") sys.exit(1) def safe_copytree(src, dst): """ Copy directory tree while: - Preserving metadata - Skipping reparse points - Copying only newer files """ for root, dirs, files in os.walk(src): # Skip reparse points (junctions, symlinks) if os.path.islink(root): logging.warning(f"Skipping symlink: {root}") continue rel_path = os.path.relpath(root, src) dest_dir = os.path.join(dst, rel_path) os.makedirs(dest_dir, exist_ok=True) for file in files: src_file = os.path.join(root, file) dst_file = os.path.join(dest_dir, file) try: if not os.path.exists(dst_file) or ( os.path.getmtime(src_file) > os.path.getmtime(dst_file) ): shutil.copy2(src_file, dst_file) logging.info(f"Copied: {src_file} -> {dst_file}") else: logging.info(f"Skipped (up-to-date): {dst_file}") except Exception as e: logging.error(f"Failed copying {src_file}: {e}") def migrate_folder(folder_relative_path): src_path = os.path.join(SOURCE_ROOT, folder_relative_path) dst_path = os.path.join(DEST_ROOT, folder_relative_path) if not os.path.exists(src_path): logging.error(f"Source not found: {src_path}") return logging.info(f"Starting migration: {src_path} -> {dst_path}") safe_copytree(src_path, dst_path) logging.info(f"Completed migration: {folder_relative_path}") # ======================= # MAIN # ======================= def main(): ensure_admin() logging.info("==== Folder Migration Started ====") for folder in FOLDERS_TO_MIGRATE: migrate_folder(folder) logging.info("==== Folder Migration Completed ====") logging.info(f"Log file saved to: {LOG_FILE}") if __name__ == "__main__": if not os.name == "nt": logging.error("This script is intended for Windows only.") sys.exit(1) main()When I execute this using IDLE on the destination PC (running IDLE as Administrator) I get the following log file output:
2025-12-29 06:43:35,182 [INFO] ==== Folder Migration Started ==== 2025-12-29 06:43:35,196 [ERROR] Source not found: D:\dgarrard 2025-12-29 06:43:35,204 [ERROR] Source not found: D:\PNC\\ 2025-12-29 06:43:35,212 [ERROR] Source not found: D:\Installers 2025-12-29 06:43:35,220 [ERROR] Source not found: D:\Nufocus 2025-12-29 06:43:35,228 [ERROR] Source not found: D:\openssl 2025-12-29 06:43:35,237 [ERROR] Source not found: D:\win-acme 2025-12-29 06:43:35,245 [ERROR] Source not found: D:\ProgramData\win-acme 2025-12-29 06:43:35,253 [ERROR] Source not found: D:\Program Files\Inkscape 2025-12-29 06:43:35,263 [ERROR] Source not found: D:\MYPROGRAMS\wkhtmltopdf 2025-12-29 06:43:35,271 [INFO] ==== Folder Migration Completed ==== 2025-12-29 06:43:35,278 [INFO] Log file saved to: C:\migration_log_20251229_064335.logThe source PC is available on the network, viewable in the Windows file browser on the destination PC so I don't understand what I am doing wrong. Seems it is related to my definition of volumes and/or folders.
Thank you
