''' Created on 26 janv. 2016 Convenient methods for manage files and directories @author: olivier.massot ''' import os import shutil import subprocess __VERSION__ = "0.1" def fdir(path): """return the parent directory of the file or directory (no existence control)""" return os.path.join(os.path.dirname(path), "") def fname(chemin, ext=True): """return the name of the file ext: return the name with its extension (no existence control)""" if not ext: chemin = os.path.splitext(chemin)[0] return os.path.basename(chemin) def fext(chemin): """return the extension of the file (no existence control)""" try: return os.path.splitext(chemin)[1] except IndexError: return "" def fexists(path): """test the existence of a file or directory""" return os.path.exists(os.path.normpath(path)) def fishttp(path): """is the path a web url?""" return path[0:7] == "http://" or path[0:8] == "https://" def frun(path): """run/open the required file, directory, webpage...""" if not fishttp(path): path = os.path.normpath(path) try: os.startfile(path) except AttributeError: subprocess.call(['open', path]) def flist(target_dir, recursive=False, listdirs=False, listfiles=True, complete_paths=False): """list the subdirectories and/or the files of the directory; """ if not os.path.isdir(target_dir): raise ValueError("'{var}' is not an valid directory".format(var=target_dir)) result = [] for root, dirs, files in os.walk(target_dir): if listdirs: if complete_paths: dirs = [os.path.join(root, d) for d in dirs] result.extend(dirs) if listfiles: if complete_paths: files = [os.path.join(root, f) for f in files] result.extend(files) if not recursive: break return result def fcopy(file_path, target, erase=False): """copy the file - If target is a directory, copy the file in this directory and keep its name - If target is a file path, copy the file to match this path if erase is True but there is already a file at this path, append a suffix '_X' to the file name""" file_path = os.path.normpath(file_path) cible = os.path.normpath(target) if not os.path.isfile(file_path): raise IOError("File {file_path} does not exist".format(file_path=file_path)) if not os.path.isdir(target): if len(fname(target)) > 0: target_dir = os.path.dirname(target) else: raise IOError("{target_dir} is not a valid target".format(target_dir=target_dir)) else: target_dir = cible name, ext = (fname(target, False), fext(target)) if len(fname(target)) > 0 \ else (fname(file_path, False), fext(file_path)) target = os.path.join(target_dir, '%s%s' % (name, ext)) if not erase: counter = 1 while fexists(target): counter += 1 target = os.path.join(target_dir, '%s_%d%s' % (name, counter, ext)) shutil.copyfile(file_path, target) return target def faccess(path, mode="r"): """return True if user has an access to the directory or file in parameter Warning: a negative answer could be caused by a missing access or by an impossibility to connect to the drive""" if mode not in ("r", "w"): raise ValueError("mode should be 'r' or 'w'") not_found = False path = os.path.normpath(path) try: with open(path, mode) as _: pass return True except (PermissionError, FileNotFoundError, OSError): not_found = True if not_found: if mode == "r": try: next(os.walk(path)) except StopIteration: return False return True else: try: with open(os.path.join(path, "__test__"), "w") as _: pass os.remove(os.path.join(path, "__test__")) return True except PermissionError: return False else: raise FileNotFoundError("File {path} does not exist".format(path=path)) def fjoin(*args): """recursively the paths in parameter""" result = "" for path in args: result = os.path.join(result, os.path.normpath(path)) return result def fmkdir(dirpath): """ create the directory recursively """ sub_path = os.path.dirname(dirpath) if not os.path.exists(sub_path): fmkdir(sub_path) if not os.path.exists(dirpath): os.mkdir(dirpath) def frmdir(dirpath): """delete the directory, even it is not empty""" shutil.rmtree(dirpath) def fhumansize(size): """return a human readable size of file""" suffixes = ['bytes', 'kB', 'MB', 'GB', 'TB'] suffix_index = 0 while size >= 1024: suffix_index += 1 #increment the index of the suffix size = size/1024.0 #apply the division return "{0:03.2f} {1}".format(size, suffixes[suffix_index]) if suffix_index > 0 \ else "{0} {1}".format(size, suffixes[suffix_index])