#!/usr/bin/env python3 import argparse import os import shutil import sys def main(): parser = argparse.ArgumentParser( description="Given a list of directories, this script will copy the contents of all of " "them into the first directory, erroring out if any duplicate files are found." ) parser.add_argument( "--ignore-duplicates", action="store_true", help="Don't error out on duplicate files, just skip them. The file from the earliest " "directory listed on the command line will be the winner." ) parser.add_argument( "--file-list", help="Path to a text file containing paths relative to in_dir. Only these paths will be " "copied out of in_dir." ) parser.add_argument("out_dir") parser.add_argument("in_dir") args = parser.parse_args() if not os.path.isdir(args.out_dir): sys.exit(f"error: {args.out_dir} must be a directory") if not os.path.isdir(args.in_dir): sys.exit(f"error: {args.in_dir} must be a directory") file_list = None if args.file_list: with open(file_list_file, "r") as f: file_list = f.read().strip().splitlines() in_dir = args.in_dir for root, dirs, files in os.walk(in_dir): rel_root = os.path.relpath(root, in_dir) dst_root = os.path.join(args.out_dir, rel_root) made_parent_dirs = False for f in files: src = os.path.join(root, f) dst = os.path.join(dst_root, f) p = os.path.normpath(os.path.join(rel_root, f)) if file_list is not None and p not in file_list: continue if os.path.lexists(dst): if args.ignore_duplicates: continue sys.exit(f"error: {p} exists in both {args.out_dir} and {in_dir}") if not made_parent_dirs: os.makedirs(dst_root, exist_ok=True) made_parent_dirs = True shutil.copy2(src, dst, follow_symlinks=False) if __name__ == "__main__": main()