#!/usr/bin/env python3 """ Recursively copy a folder to a destination, excluding hidden files and folders. This script copies all files and subfolders from a source directory to a destination directory, skipping any hidden files or folders (those starting with a dot). Usage: ./copy_folder.py SOURCE DESTINATION Arguments: SOURCE Path to the source folder to copy from. DESTINATION Path to the destination folder to copy to. Example: ./copy_folder.py ~/my_project ~/backup/my_project Notes: - Hidden files/folders (starting with a dot) are excluded. - The destination folder will be created if it does not exist. - Existing files in the destination will be overwritten. """ import argparse import os import shutil from pathlib import Path def copy_folder_excluding_hidden(src, dst): """Recursively copy src to dst, excluding hidden files and folders.""" src_path = Path(src) dst_path = Path(dst) if not src_path.exists(): raise FileNotFoundError(f"Source folder does not exist: {src_path}") if not dst_path.exists(): dst_path.mkdir(parents=True, exist_ok=True) for item in src_path.iterdir(): if item.name.startswith('.'): continue # Skip hidden files/folders if item.is_dir(): shutil.copytree(item, dst_path / item.name, ignore=shutil.ignore_patterns('.*')) else: shutil.copy2(item, dst_path / item.name) def main(): parser = argparse.ArgumentParser( description="Recursively copy a folder, excluding hidden files and folders." ) parser.add_argument( "source", type=str, help="Source folder to copy from." ) parser.add_argument( "destination", type=str, help="Destination folder to copy to." ) args = parser.parse_args() try: copy_folder_excluding_hidden(args.source, args.destination) print(f"Successfully copied from {args.source} to {args.destination}") except Exception as e: print(f"Error: {e}") exit(1) if __name__ == "__main__": main()