def rmdirRecursiveSub(dir, do_ignore_remove_fails): """This is a replacement for shutil.rmtree that works better under windows. Thanks to Bear at the OSAF for the code.""" if not os.path.exists(dir): return try: if os.path.islink(dir) or os.path.isfile(dir): os.remove(dir) return # Verify the directory is read/write/execute for the current user os.chmod(dir, 0700) # os.listdir below only returns a list of unicode filenames if the parameter is unicode # Thus, if a non-unicode-named dir contains a unicode filename, that filename will get garbled. # So force dir to be unicode. if not isinstance(dir, unicode): try: dir = unicode(dir, "utf-8") except: log.err("rmdirRecursive: decoding from UTF-8 failed (ignoring)") try: list = os.listdir(dir) except WindowsError, e: msg = ("rmdirRecursive: unable to listdir %s (%s). Trying to " "remove like a dir" % (dir, e.strerror.decode('mbcs'))) log.msg(msg.encode('utf-8')) os.rmdir(dir) return for name in list: full_name = os.path.join(dir, name) # on Windows, if we don't have write permission we can't remove # the file/directory either, so turn that on if os.name == 'nt': if not os.access(full_name, os.W_OK): # I think this is now redundant, but I don't have an NT # machine to test on, so I'm going to leave it in place # -warner os.chmod(full_name, 0600) if os.path.islink(full_name): os.remove(full_name) # as suggested in bug #792 elif os.path.isdir(full_name): rmdirRecursiveSub(full_name, True) else: if os.path.isfile(full_name): os.chmod(full_name, 0700) os.remove(full_name) os.rmdir(dir) except OSError as e: if e.errno in (errno.ENOTEMPTY, errno.EBUSY, errno.EACCES): if not do_ignore_remove_fails: msg = None try: list2 = os.listdir(dir) msg = 'rmdirRecursive: directory not empty: {0}. Contains: {1}. New: {2}.' msg = msg.format(repr(dir), repr(list2), repr(sorted(set(list2) - set(list)))) except: pass if msg is None: raise raise OSError(e.errno, msg) elif e.errno == errno.ENOENT: pass else: raise def rmdirRecursive(dir): tries_left = 5 # number of tries delay_between_tries = 5 # dely in seconds between tries while True: try: rmdirRecursiveSub(dir, False) break except OSError as e: tries_left -= 1 if not e.errno in (errno.ENOTEMPTY, errno.EBUSY, errno.EACCES): raise if tries_left <= 0: raise # try again after some waiting time.sleep(delay_between_tries)