utils_fs.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import os
  2. import shutil
  3. def get_path_stem(path):
  4. """
  5. References:
  6. `std::filesystem::path::stem` since C++17
  7. """
  8. return os.path.splitext(os.path.basename(path))[0]
  9. def replace_path_stem(path, new_stem):
  10. dirname, basename = os.path.split(path)
  11. stem, extname = os.path.splitext(basename)
  12. if isinstance(new_stem, str):
  13. return os.path.join(dirname, new_stem + extname)
  14. elif hasattr(new_stem, '__call__'):
  15. return os.path.join(dirname, new_stem(stem) + extname)
  16. else:
  17. raise ValueError('Unsupported Type!')
  18. def get_path_extension(path):
  19. """
  20. References:
  21. `std::filesystem::path::extension` since C++17
  22. Notes:
  23. Not fully consistent with `std::filesystem::path::extension`
  24. """
  25. return os.path.splitext(os.path.basename(path))[1]
  26. def replace_path_extension(path, new_extname=None):
  27. """Replaces the extension with new_extname or removes it when the default value is used.
  28. Firstly, if this path has an extension, it is removed. Then, a dot character is appended
  29. to the pathname, if new_extname is not empty or does not begin with a dot character.
  30. References:
  31. `std::filesystem::path::replace_extension` since C++17
  32. """
  33. filename_wo_ext = os.path.splitext(path)[0]
  34. if new_extname == '' or new_extname is None:
  35. return filename_wo_ext
  36. elif new_extname.startswith('.'):
  37. return ''.join([filename_wo_ext, new_extname])
  38. else:
  39. return '.'.join([filename_wo_ext, new_extname])
  40. def makedirs(name, mode=0o755):
  41. """
  42. References:
  43. mmcv.mkdir_or_exist
  44. """
  45. if name == '':
  46. return
  47. name = os.path.expanduser(name)
  48. os.makedirs(name, mode=mode, exist_ok=True)
  49. def listdirs(paths, path_sep=None, full_path=True):
  50. """Enhancement on `os.listdir`
  51. """
  52. assert isinstance(paths, (str, tuple, list))
  53. if isinstance(paths, str):
  54. path_sep = path_sep or os.path.pathsep
  55. paths = paths.split(path_sep)
  56. all_filenames = []
  57. for path in paths:
  58. path_ex = os.path.expanduser(path)
  59. filenames = os.listdir(path_ex)
  60. if full_path:
  61. filenames = [os.path.join(path_ex, filename) for filename in filenames]
  62. all_filenames.extend(filenames)
  63. return all_filenames
  64. def get_all_filenames(dirname, extensions=None, is_valid_file=None):
  65. if (extensions is not None) and (is_valid_file is not None):
  66. raise ValueError("Both extensions and is_valid_file cannot "
  67. "be not None at the same time")
  68. if is_valid_file is None:
  69. if extensions is not None:
  70. def is_valid_file(filename):
  71. return filename.lower().endswith(extensions)
  72. else:
  73. def is_valid_file(filename):
  74. return True
  75. all_filenames = []
  76. dirname = os.path.expanduser(dirname)
  77. for root, _, filenames in sorted(os.walk(dirname, followlinks=True)):
  78. for filename in sorted(filenames):
  79. path = os.path.join(root, filename)
  80. if is_valid_file(path):
  81. all_filenames.append(path)
  82. return all_filenames
  83. def get_top_level_dirs(path, full_path=True):
  84. if path is None:
  85. path = os.getcwd()
  86. path_ex = os.path.expanduser(path)
  87. filenames = os.listdir(path_ex)
  88. if full_path:
  89. return [os.path.join(path_ex, item) for item in filenames
  90. if os.path.isdir(os.path.join(path_ex, item))]
  91. else:
  92. return [item for item in filenames
  93. if os.path.isdir(os.path.join(path_ex, item))]
  94. def copy_file(src, dst_dir, action_if_exist=None):
  95. """
  96. Args:
  97. src: source file path
  98. dst_dir: dest dir
  99. action_if_exist:
  100. None: when dest file exists, no operation
  101. overwritten: when dest file exists, overwritten
  102. rename: when dest file exists, rename it
  103. Returns:
  104. dest file basename
  105. """
  106. src_basename = os.path.basename(src)
  107. dst_fullname = os.path.join(dst_dir, src_basename)
  108. if action_if_exist is None:
  109. if not os.path.exists(dst_fullname):
  110. makedirs(dst_dir)
  111. shutil.copy(src, dst_dir)
  112. elif action_if_exist.lower() == 'overwritten':
  113. makedirs(dst_dir)
  114. # shutil.copy
  115. # If dst is a directory, a file with the same basename as src is
  116. # created (or overwritten) in the directory specified.
  117. shutil.copy(src, dst_dir)
  118. elif action_if_exist.lower() == 'rename':
  119. src_stem, src_extname = os.path.splitext(src_basename)
  120. suffix = 2
  121. while os.path.exists(dst_fullname):
  122. dst_basename = '{} ({}){}'.format(src_stem, suffix, src_extname)
  123. dst_fullname = os.path.join(dst_dir, dst_basename)
  124. suffix += 1
  125. else:
  126. makedirs(dst_dir)
  127. shutil.copy(src, dst_fullname)
  128. else:
  129. raise ValueError('Invalid action_if_exist, got {}.'.format(action_if_exist))
  130. return os.path.basename(dst_fullname)
  131. def move_file(src, dst_dir, action_if_exist=None):
  132. """
  133. Args:
  134. src: source file path
  135. dst_dir: dest dir
  136. action_if_exist:
  137. None: when dest file exists, no operation
  138. overwritten: when dest file exists, overwritten
  139. rename: when dest file exists, rename it
  140. Returns:
  141. dest file basename
  142. """
  143. src_basename = os.path.basename(src)
  144. dst_fullname = os.path.join(dst_dir, src_basename)
  145. if action_if_exist is None:
  146. if not os.path.exists(dst_fullname):
  147. makedirs(dst_dir)
  148. shutil.move(src, dst_dir)
  149. elif action_if_exist.lower() == 'overwritten':
  150. if os.path.exists(dst_fullname):
  151. os.remove(dst_fullname)
  152. makedirs(dst_dir)
  153. # shutil.move
  154. # If the destination already exists but is not a directory,
  155. # it may be overwritten depending on os.rename() semantics.
  156. shutil.move(src, dst_dir)
  157. elif action_if_exist.lower() == 'rename':
  158. src_stem, src_extname = os.path.splitext(src_basename)
  159. suffix = 2
  160. while os.path.exists(dst_fullname):
  161. dst_basename = '{} ({}){}'.format(src_stem, suffix, src_extname)
  162. dst_fullname = os.path.join(dst_dir, dst_basename)
  163. suffix += 1
  164. else:
  165. makedirs(dst_dir)
  166. shutil.move(src, dst_fullname)
  167. else:
  168. raise ValueError('Invalid action_if_exist, got {}.'.format(action_if_exist))
  169. return os.path.basename(dst_fullname)