1*4882a593Smuzhiyun#!/usr/bin/env python3 2*4882a593Smuzhiyun# 3*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 4*4882a593Smuzhiyun# 5*4882a593Smuzhiyun# Allow copying of $1 to $2 but if files in $1 disappear during the copy operation, 6*4882a593Smuzhiyun# don't error. 7*4882a593Smuzhiyun# Also don't error if $1 disappears. 8*4882a593Smuzhiyun# 9*4882a593Smuzhiyun 10*4882a593Smuzhiyunimport sys 11*4882a593Smuzhiyunimport os 12*4882a593Smuzhiyunimport shutil 13*4882a593Smuzhiyun 14*4882a593Smuzhiyundef copytree(src, dst, symlinks=False, ignore=None): 15*4882a593Smuzhiyun """Based on shutil.copytree""" 16*4882a593Smuzhiyun names = os.listdir(src) 17*4882a593Smuzhiyun try: 18*4882a593Smuzhiyun os.makedirs(dst) 19*4882a593Smuzhiyun except OSError: 20*4882a593Smuzhiyun # Already exists 21*4882a593Smuzhiyun pass 22*4882a593Smuzhiyun errors = [] 23*4882a593Smuzhiyun for name in names: 24*4882a593Smuzhiyun srcname = os.path.join(src, name) 25*4882a593Smuzhiyun dstname = os.path.join(dst, name) 26*4882a593Smuzhiyun try: 27*4882a593Smuzhiyun d = dstname 28*4882a593Smuzhiyun if os.path.isdir(dstname): 29*4882a593Smuzhiyun d = os.path.join(dstname, os.path.basename(srcname)) 30*4882a593Smuzhiyun if os.path.exists(d): 31*4882a593Smuzhiyun continue 32*4882a593Smuzhiyun try: 33*4882a593Smuzhiyun os.link(srcname, dstname) 34*4882a593Smuzhiyun except OSError: 35*4882a593Smuzhiyun shutil.copy2(srcname, dstname) 36*4882a593Smuzhiyun # catch the Error from the recursive copytree so that we can 37*4882a593Smuzhiyun # continue with other files 38*4882a593Smuzhiyun except shutil.Error as err: 39*4882a593Smuzhiyun errors.extend(err.args[0]) 40*4882a593Smuzhiyun except EnvironmentError as why: 41*4882a593Smuzhiyun errors.append((srcname, dstname, str(why))) 42*4882a593Smuzhiyun try: 43*4882a593Smuzhiyun shutil.copystat(src, dst) 44*4882a593Smuzhiyun except OSError as why: 45*4882a593Smuzhiyun errors.extend((src, dst, str(why))) 46*4882a593Smuzhiyun if errors: 47*4882a593Smuzhiyun raise shutil.Error(errors) 48*4882a593Smuzhiyun 49*4882a593Smuzhiyuntry: 50*4882a593Smuzhiyun copytree(sys.argv[1], sys.argv[2]) 51*4882a593Smuzhiyunexcept shutil.Error: 52*4882a593Smuzhiyun pass 53*4882a593Smuzhiyunexcept OSError: 54*4882a593Smuzhiyun pass 55