cornsnake.util_dir

Working with directories, files, and file paths.

Documentation

  1"""
  2Working with directories, files, and file paths.
  3
  4[Documentation](http://docs.mrseanryan.cornsnake.s3-website-eu-west-1.amazonaws.com/cornsnake/util_dir.html)
  5"""
  6
  7import os
  8from glob import glob
  9import re
 10import shutil
 11from pathlib import Path
 12
 13from . import util_os
 14from . import util_robust_delete
 15
 16TOTAL_BYTES_IN_GIGABYTE = 1000000000
 17
 18delete_dirs = util_robust_delete.delete_dirs  # allow access via this file
 19
 20
 21def copy_directory(from_path: str, to_path: str) -> None:
 22    """
 23    Copy a directory from one location to another.
 24
 25    Args:
 26    from_path (str): The path of the directory to copy from.
 27    to_path (str): The path of the directory to copy to.
 28    """
 29    shutil.copytree(from_path, to_path)
 30
 31
 32def ensure_dir_exists(target_dir: str) -> None:
 33    """
 34    Ensure that a directory exists, creating it if necessary.
 35
 36    Args:
 37    target_dir (str): The path of the directory to ensure existence of.
 38    """
 39    if not os.path.exists(target_dir):
 40        os.makedirs(target_dir)
 41
 42
 43def find_files_by_extension(dir_path: str, extension: str) -> list[str]:
 44    """
 45    Find files in a directory by a specific file extension.
 46
 47    Args:
 48    dir_path (str): The path of the directory to search for files.
 49    extension (str): The file extension to search for.
 50
 51    Example: ('c:\\temp\\x', '.json') -> ['c:\\temp\\x\\1.json', 'c:\\temp\\x\\2.json']
 52
 53    Returns:
 54    list: A list of file paths with the specified extension.
 55    """
 56    found_files = []
 57    contents = os.listdir(dir_path)
 58    for content in contents:
 59        path_to_sub = os.path.join(dir_path, content)
 60        if os.path.isfile(path_to_sub) and path_to_sub.endswith(extension):
 61            found_files.append(path_to_sub)
 62    return found_files
 63
 64
 65def find_files(dir_path: str) -> list[str]:
 66    """Find all files in the given directory."""
 67    found_files = []
 68    contents = os.listdir(dir_path)
 69    for content in contents:
 70        path_to_sub = os.path.join(dir_path, content)
 71        if os.path.isfile(path_to_sub):
 72            found_files.append(path_to_sub)
 73    return found_files
 74
 75
 76def find_files_recursively(dir_path: str, extension: str = ".*") -> list[str]:
 77    result = [
 78        y for x in os.walk(dir_path) for y in glob(os.path.join(x[0], f"*{extension}"))
 79    ]
 80    return result
 81
 82
 83def get_dir_parts(path_to_file: str) -> list[str]:
 84    """
 85    Get the directory components of the given file path.
 86
 87    Example: 'c:\\temp\\x\\my-file.txt' -> ['c','temp','x']
 88    """
 89    path_to_dir = os.path.dirname(path_to_file)
 90    path = os.path.normpath(path_to_dir)
 91    return path.split(os.sep)
 92
 93
 94def get_directory_of_this_script(____file__: str) -> str:
 95    """
 96    Get the directory that contains this script.
 97
 98    Args:
 99    __file__ (str): The path to this Python script file.
100    Returns:
101    The absolute path to directory containing your Python script file.
102    """
103    return os.path.dirname(os.path.realpath(____file__))
104
105
106def get_parent_dir(my_path: str) -> str:
107    """Get the absolute path of the parent directory of the given directory."""
108    return str(Path(my_path).parent.absolute())
109
110
111def get_total_dir_size_in_bytes(start_path: str) -> int:
112    total_size = 0
113    for dirpath, _dirnames, filenames in os.walk(start_path):
114        for f in filenames:
115            fp = os.path.join(dirpath, f)
116            # skip if it is symbolic link
117            if not os.path.islink(fp):
118                fp_allow_long_path = "\\\\?\\" + fp if util_os.is_windows() else fp
119                total_size += os.path.getsize(fp_allow_long_path)
120
121    return total_size
122
123
124def get_total_dir_size_in_gigabytes(start_path: str) -> float:
125    """Calculate the total size of a directory in gigabytes.
126    Args:
127    start_path (str): The path of the directory to calculate size of.
128    Returns:
129    float: The total size of the directory in gigabytes."""
130    return get_total_dir_size_in_bytes(start_path) / TOTAL_BYTES_IN_GIGABYTE
131
132
133def get_unique_dirpath(path_to_dir: str) -> str:
134    """
135    Get a unique directory path similar to the given path.
136    """
137
138    def _ends_with_hyphen_number(path: str) -> bool:
139        m = re.search(r"-\d+$", path)
140        return m is not None
141
142    # Avoid appending like x-01-02-03
143    if _ends_with_hyphen_number(path_to_dir):
144        path_to_dir = path_to_dir[:-3]
145
146    suffix = 2
147    path_to_dir_new = path_to_dir
148    while os.path.exists(path_to_dir_new):
149        path_to_dir_new = f"{path_to_dir}-{suffix:02}"
150        suffix += 1
151    return path_to_dir_new
152
153
154def is_empty_directory(path_to_file: str) -> bool:
155    """Check if a directory is empty.
156    Args:
157    path_to_file (str): The path of the directory to check.
158    Returns:
159    bool: True if the directory is empty, False otherwise."""
160    if os.path.isfile(path_to_file):
161        return False
162    contents = os.listdir(path_to_file)
163    return len(contents) == 0
164
165
166def is_empty_directory_only_subdirectories(path_to_file: str) -> bool:
167    """Check if a directory is empty by inspecting subdirectories.
168    Args:
169    path_to_file (str): The path of the directory to check.
170    Returns:
171    bool: True if the directory is empty or only contains empty subdirectories, False otherwise.
172    """
173    if os.path.isfile(path_to_file):
174        return False
175    contents = os.listdir(path_to_file)
176    for content in contents:
177        path_to_sub = os.path.join(path_to_file, content)
178        if os.path.isfile(path_to_sub):
179            return False
180        if not os.path.isfile(path_to_sub):
181            is_empty = is_empty_directory_only_subdirectories(path_to_sub)
182            if not is_empty:
183                return False
184    return True
185
186
187def move_directory(path_to_dir: str, path_to_dir_renamed: str) -> None:
188    shutil.move(path_to_dir, path_to_dir_renamed)
TOTAL_BYTES_IN_GIGABYTE = 1000000000
def delete_dirs(temp_dirs_to_delete: str) -> None:
74def delete_dirs(temp_dirs_to_delete: str) -> None:
75    """
76    Delete directories and their contents.
77    - Python holds on to some paths - so delete as much as we can
78
79    Args:
80    temp_dirs_to_delete (list): A list of directory paths to be deleted.
81    """
82    dirs_with_locked_items = []
83    # faster delete:
84    for temp_dir in temp_dirs_to_delete:
85        try:
86            _rmrf(temp_dir)
87        except FileNotFoundError:
88            dirs_with_locked_items.append(temp_dir)
89            # Intentionally NOT passing exception onwards
90        except PermissionError:
91            dirs_with_locked_items.append(temp_dir)
92            # Intentionally NOT passing exception onwards
93
94    # slower, more robust delete:
95    for temp_dir in dirs_with_locked_items:
96        _delete_dir_contents(temp_dir)

Delete directories and their contents.

  • Python holds on to some paths - so delete as much as we can

Args: temp_dirs_to_delete (list): A list of directory paths to be deleted.

def copy_directory(from_path: str, to_path: str) -> None:
22def copy_directory(from_path: str, to_path: str) -> None:
23    """
24    Copy a directory from one location to another.
25
26    Args:
27    from_path (str): The path of the directory to copy from.
28    to_path (str): The path of the directory to copy to.
29    """
30    shutil.copytree(from_path, to_path)

Copy a directory from one location to another.

Args: from_path (str): The path of the directory to copy from. to_path (str): The path of the directory to copy to.

def ensure_dir_exists(target_dir: str) -> None:
33def ensure_dir_exists(target_dir: str) -> None:
34    """
35    Ensure that a directory exists, creating it if necessary.
36
37    Args:
38    target_dir (str): The path of the directory to ensure existence of.
39    """
40    if not os.path.exists(target_dir):
41        os.makedirs(target_dir)

Ensure that a directory exists, creating it if necessary.

Args: target_dir (str): The path of the directory to ensure existence of.

def find_files_by_extension(dir_path: str, extension: str) -> list[str]:
44def find_files_by_extension(dir_path: str, extension: str) -> list[str]:
45    """
46    Find files in a directory by a specific file extension.
47
48    Args:
49    dir_path (str): The path of the directory to search for files.
50    extension (str): The file extension to search for.
51
52    Example: ('c:\\temp\\x', '.json') -> ['c:\\temp\\x\\1.json', 'c:\\temp\\x\\2.json']
53
54    Returns:
55    list: A list of file paths with the specified extension.
56    """
57    found_files = []
58    contents = os.listdir(dir_path)
59    for content in contents:
60        path_to_sub = os.path.join(dir_path, content)
61        if os.path.isfile(path_to_sub) and path_to_sub.endswith(extension):
62            found_files.append(path_to_sub)
63    return found_files

Find files in a directory by a specific file extension.

Args: dir_path (str): The path of the directory to search for files. extension (str): The file extension to search for.

Example: ('c:\temp\x', '.json') -> ['c:\temp\x\1.json', 'c:\temp\x\2.json']

Returns: list: A list of file paths with the specified extension.

def find_files(dir_path: str) -> list[str]:
66def find_files(dir_path: str) -> list[str]:
67    """Find all files in the given directory."""
68    found_files = []
69    contents = os.listdir(dir_path)
70    for content in contents:
71        path_to_sub = os.path.join(dir_path, content)
72        if os.path.isfile(path_to_sub):
73            found_files.append(path_to_sub)
74    return found_files

Find all files in the given directory.

def find_files_recursively(dir_path: str, extension: str = '.*') -> list[str]:
77def find_files_recursively(dir_path: str, extension: str = ".*") -> list[str]:
78    result = [
79        y for x in os.walk(dir_path) for y in glob(os.path.join(x[0], f"*{extension}"))
80    ]
81    return result
def get_dir_parts(path_to_file: str) -> list[str]:
84def get_dir_parts(path_to_file: str) -> list[str]:
85    """
86    Get the directory components of the given file path.
87
88    Example: 'c:\\temp\\x\\my-file.txt' -> ['c','temp','x']
89    """
90    path_to_dir = os.path.dirname(path_to_file)
91    path = os.path.normpath(path_to_dir)
92    return path.split(os.sep)

Get the directory components of the given file path.

Example: 'c:\temp\x\my-file.txt' -> ['c','temp','x']

def get_directory_of_this_script(____file__: str) -> str:
 95def get_directory_of_this_script(____file__: str) -> str:
 96    """
 97    Get the directory that contains this script.
 98
 99    Args:
100    __file__ (str): The path to this Python script file.
101    Returns:
102    The absolute path to directory containing your Python script file.
103    """
104    return os.path.dirname(os.path.realpath(____file__))

Get the directory that contains this script.

Args: __file__ (str): The path to this Python script file. Returns: The absolute path to directory containing your Python script file.

def get_parent_dir(my_path: str) -> str:
107def get_parent_dir(my_path: str) -> str:
108    """Get the absolute path of the parent directory of the given directory."""
109    return str(Path(my_path).parent.absolute())

Get the absolute path of the parent directory of the given directory.

def get_total_dir_size_in_bytes(start_path: str) -> int:
112def get_total_dir_size_in_bytes(start_path: str) -> int:
113    total_size = 0
114    for dirpath, _dirnames, filenames in os.walk(start_path):
115        for f in filenames:
116            fp = os.path.join(dirpath, f)
117            # skip if it is symbolic link
118            if not os.path.islink(fp):
119                fp_allow_long_path = "\\\\?\\" + fp if util_os.is_windows() else fp
120                total_size += os.path.getsize(fp_allow_long_path)
121
122    return total_size
def get_total_dir_size_in_gigabytes(start_path: str) -> float:
125def get_total_dir_size_in_gigabytes(start_path: str) -> float:
126    """Calculate the total size of a directory in gigabytes.
127    Args:
128    start_path (str): The path of the directory to calculate size of.
129    Returns:
130    float: The total size of the directory in gigabytes."""
131    return get_total_dir_size_in_bytes(start_path) / TOTAL_BYTES_IN_GIGABYTE

Calculate the total size of a directory in gigabytes. Args: start_path (str): The path of the directory to calculate size of. Returns: float: The total size of the directory in gigabytes.

def get_unique_dirpath(path_to_dir: str) -> str:
134def get_unique_dirpath(path_to_dir: str) -> str:
135    """
136    Get a unique directory path similar to the given path.
137    """
138
139    def _ends_with_hyphen_number(path: str) -> bool:
140        m = re.search(r"-\d+$", path)
141        return m is not None
142
143    # Avoid appending like x-01-02-03
144    if _ends_with_hyphen_number(path_to_dir):
145        path_to_dir = path_to_dir[:-3]
146
147    suffix = 2
148    path_to_dir_new = path_to_dir
149    while os.path.exists(path_to_dir_new):
150        path_to_dir_new = f"{path_to_dir}-{suffix:02}"
151        suffix += 1
152    return path_to_dir_new

Get a unique directory path similar to the given path.

def is_empty_directory(path_to_file: str) -> bool:
155def is_empty_directory(path_to_file: str) -> bool:
156    """Check if a directory is empty.
157    Args:
158    path_to_file (str): The path of the directory to check.
159    Returns:
160    bool: True if the directory is empty, False otherwise."""
161    if os.path.isfile(path_to_file):
162        return False
163    contents = os.listdir(path_to_file)
164    return len(contents) == 0

Check if a directory is empty. Args: path_to_file (str): The path of the directory to check. Returns: bool: True if the directory is empty, False otherwise.

def is_empty_directory_only_subdirectories(path_to_file: str) -> bool:
167def is_empty_directory_only_subdirectories(path_to_file: str) -> bool:
168    """Check if a directory is empty by inspecting subdirectories.
169    Args:
170    path_to_file (str): The path of the directory to check.
171    Returns:
172    bool: True if the directory is empty or only contains empty subdirectories, False otherwise.
173    """
174    if os.path.isfile(path_to_file):
175        return False
176    contents = os.listdir(path_to_file)
177    for content in contents:
178        path_to_sub = os.path.join(path_to_file, content)
179        if os.path.isfile(path_to_sub):
180            return False
181        if not os.path.isfile(path_to_sub):
182            is_empty = is_empty_directory_only_subdirectories(path_to_sub)
183            if not is_empty:
184                return False
185    return True

Check if a directory is empty by inspecting subdirectories. Args: path_to_file (str): The path of the directory to check. Returns: bool: True if the directory is empty or only contains empty subdirectories, False otherwise.

def move_directory(path_to_dir: str, path_to_dir_renamed: str) -> None:
188def move_directory(path_to_dir: str, path_to_dir_renamed: str) -> None:
189    shutil.move(path_to_dir, path_to_dir_renamed)