1*333d2b36SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*333d2b36SAndroid Build Coastguard Workerimport argparse 3*333d2b36SAndroid Build Coastguard Workerimport os 4*333d2b36SAndroid Build Coastguard Workerimport shutil 5*333d2b36SAndroid Build Coastguard Workerimport sys 6*333d2b36SAndroid Build Coastguard Worker 7*333d2b36SAndroid Build Coastguard Workerdef main(): 8*333d2b36SAndroid Build Coastguard Worker parser = argparse.ArgumentParser( 9*333d2b36SAndroid Build Coastguard Worker description="Given a list of directories, this script will copy the contents of all of " 10*333d2b36SAndroid Build Coastguard Worker "them into the first directory, erroring out if any duplicate files are found." 11*333d2b36SAndroid Build Coastguard Worker ) 12*333d2b36SAndroid Build Coastguard Worker parser.add_argument( 13*333d2b36SAndroid Build Coastguard Worker "--ignore-duplicates", 14*333d2b36SAndroid Build Coastguard Worker action="store_true", 15*333d2b36SAndroid Build Coastguard Worker help="Don't error out on duplicate files, just skip them. The file from the earliest " 16*333d2b36SAndroid Build Coastguard Worker "directory listed on the command line will be the winner." 17*333d2b36SAndroid Build Coastguard Worker ) 18*333d2b36SAndroid Build Coastguard Worker parser.add_argument( 19*333d2b36SAndroid Build Coastguard Worker "--file-list", 20*333d2b36SAndroid Build Coastguard Worker help="Path to a text file containing paths relative to in_dir. Only these paths will be " 21*333d2b36SAndroid Build Coastguard Worker "copied out of in_dir." 22*333d2b36SAndroid Build Coastguard Worker ) 23*333d2b36SAndroid Build Coastguard Worker parser.add_argument("out_dir") 24*333d2b36SAndroid Build Coastguard Worker parser.add_argument("in_dir") 25*333d2b36SAndroid Build Coastguard Worker args = parser.parse_args() 26*333d2b36SAndroid Build Coastguard Worker 27*333d2b36SAndroid Build Coastguard Worker if not os.path.isdir(args.out_dir): 28*333d2b36SAndroid Build Coastguard Worker sys.exit(f"error: {args.out_dir} must be a directory") 29*333d2b36SAndroid Build Coastguard Worker if not os.path.isdir(args.in_dir): 30*333d2b36SAndroid Build Coastguard Worker sys.exit(f"error: {args.in_dir} must be a directory") 31*333d2b36SAndroid Build Coastguard Worker 32*333d2b36SAndroid Build Coastguard Worker file_list = None 33*333d2b36SAndroid Build Coastguard Worker if args.file_list: 34*333d2b36SAndroid Build Coastguard Worker with open(file_list_file, "r") as f: 35*333d2b36SAndroid Build Coastguard Worker file_list = f.read().strip().splitlines() 36*333d2b36SAndroid Build Coastguard Worker 37*333d2b36SAndroid Build Coastguard Worker in_dir = args.in_dir 38*333d2b36SAndroid Build Coastguard Worker for root, dirs, files in os.walk(in_dir): 39*333d2b36SAndroid Build Coastguard Worker rel_root = os.path.relpath(root, in_dir) 40*333d2b36SAndroid Build Coastguard Worker dst_root = os.path.join(args.out_dir, rel_root) 41*333d2b36SAndroid Build Coastguard Worker made_parent_dirs = False 42*333d2b36SAndroid Build Coastguard Worker for f in files: 43*333d2b36SAndroid Build Coastguard Worker src = os.path.join(root, f) 44*333d2b36SAndroid Build Coastguard Worker dst = os.path.join(dst_root, f) 45*333d2b36SAndroid Build Coastguard Worker p = os.path.normpath(os.path.join(rel_root, f)) 46*333d2b36SAndroid Build Coastguard Worker if file_list is not None and p not in file_list: 47*333d2b36SAndroid Build Coastguard Worker continue 48*333d2b36SAndroid Build Coastguard Worker if os.path.lexists(dst): 49*333d2b36SAndroid Build Coastguard Worker if args.ignore_duplicates: 50*333d2b36SAndroid Build Coastguard Worker continue 51*333d2b36SAndroid Build Coastguard Worker sys.exit(f"error: {p} exists in both {args.out_dir} and {in_dir}") 52*333d2b36SAndroid Build Coastguard Worker 53*333d2b36SAndroid Build Coastguard Worker if not made_parent_dirs: 54*333d2b36SAndroid Build Coastguard Worker os.makedirs(dst_root, exist_ok=True) 55*333d2b36SAndroid Build Coastguard Worker made_parent_dirs = True 56*333d2b36SAndroid Build Coastguard Worker 57*333d2b36SAndroid Build Coastguard Worker shutil.copy2(src, dst, follow_symlinks=False) 58*333d2b36SAndroid Build Coastguard Worker 59*333d2b36SAndroid Build Coastguard Workerif __name__ == "__main__": 60*333d2b36SAndroid Build Coastguard Worker main() 61