| #!/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() |