from argparse import ArgumentParser, Namespace import glob import shutil from typing import List import os from dataclasses import dataclass import time @dataclass class Arguments: source_path: str dest_path: str def dir_path(string) -> str: if os.path.isdir(string): return string else: raise NotADirectoryError(string) def addArguments(parser: ArgumentParser) -> None: parser.add_argument('from_path', type=dir_path) parser.add_argument('to_path', type=dir_path) parser.set_defaults(func=main) def parseRawArgs(args: Namespace) -> Arguments: return Arguments(args.from_path, args.to_path) def filesByExtension(source_path: str, extension: str) -> List[str]: upper_extension = extension.upper() lower_extension = extension.lower() source_files = [] source_files.extend(glob.glob(f"**/*.{upper_extension}", root_dir=source_path, recursive=True)) source_files.extend(glob.glob(f"**/*.{lower_extension}", root_dir=source_path, recursive=True)) return source_files def main(raw_args: Namespace) -> None: args = parseRawArgs(raw_args) jpegs = filesByExtension(args.source_path, "JPG") raws = filesByExtension(args.source_path, "RAF") movs = filesByExtension(args.source_path, "MOV") total_size = 0 for file in jpegs: total_size += os.path.getsize(os.path.join(args.source_path, file)) for file in raws: total_size += os.path.getsize(os.path.join(args.source_path, file)) for file in movs: total_size += os.path.getsize(os.path.join(args.source_path, file)) block_size = os.statvfs(args.dest_path).f_frsize blocks_free = os.statvfs(args.dest_path).f_bfree assert(block_size * blocks_free > total_size) for (files, subdir) in zip([jpegs, raws, movs], ["JPEG", "RAW", "MOV"]): try: os.mkdir(os.path.join(args.dest_path, subdir)) except FileExistsError: print("Warning: path exists") pass time.sleep(1) for file in files: source_file = os.path.join(args.source_path, file) dest_folder = os.path.join(args.dest_path, subdir) print(f"Copying {source_file} to {dest_folder}") shutil.copy2(source_file, dest_folder)