cornsnake.util_file

File operations including copying, reading, and writing text to files.

Documentation

  1"""
  2File operations including copying, reading, and writing text to files.
  3
  4[Documentation](http://docs.mrseanryan.cornsnake.s3-website-eu-west-1.amazonaws.com/cornsnake/util_file.html)
  5"""
  6
  7import os
  8import shutil
  9
 10from . import util_os
 11from . import util_pdf
 12from . import util_text
 13
 14
 15def backup_file_by_copying(path_to_file, backup_dir, backup_filename):
 16    """
 17    Backup the given file by copying it to a new uniquely named file.
 18    """
 19    path_to_backup = os.path.join(backup_dir, backup_filename)
 20    path_to_backup = get_unique_filepath(path_to_backup)
 21    copy_file(path_to_file, path_to_backup)
 22    return path_to_backup
 23
 24
 25def copy_file(from_path, to_path):
 26    """
 27    Copy a file from one path to another.
 28
 29    Args:
 30    from_path (str): The path of the file to copy.
 31    to_path (str): The destination path to copy the file to.
 32    """
 33    shutil.copyfile(from_path, to_path)
 34
 35
 36def delete_file(path_to_file):
 37    """
 38    Delete a file from the disk.
 39    """
 40    os.remove(path_to_file)
 41
 42
 43def get_unique_filepath(path_to_file):
 44    """
 45    Get a unique new filepath, similar to the given path.
 46    """
 47    filename_no_extension, extension = os.path.splitext(path_to_file)
 48
 49    suffix = 2
 50    while os.path.exists(path_to_file):
 51        path_to_file = f"{filename_no_extension}-{suffix:02}{extension}"
 52        suffix += 1
 53    return path_to_file
 54
 55
 56def get_this_script_dir(this_file):
 57    """
 58    Get the directory of the current script file.
 59
 60    Args:
 61    this_file (str): The path of the current script file (__file__).
 62
 63    Returns:
 64    str: The directory of the current script file.
 65    """
 66    return os.path.dirname(os.path.realpath(this_file))
 67
 68
 69def is_file_under_dir(path_to_file, path_to_dir):
 70    """
 71    Does that file exist under that directory or a sub-directory.
 72    """
 73    path_to_file = os.path.normpath(path_to_file)
 74    path_to_dir = os.path.normpath(path_to_dir) + os.sep
 75    return path_to_file.startswith(path_to_dir)
 76
 77
 78def _get_long_file_path(path_to_file):
 79    """
 80    Get the long file path for Windows.
 81
 82    Args:
 83    path_to_file (str): The original file path.
 84
 85    Returns:
 86    str: The long file path for Windows.
 87    """
 88    return "\\\\?\\" + path_to_file if util_os.is_windows() else path_to_file
 89
 90
 91def is_empty_directory_only_subdirectories(path_to_file):
 92    """
 93    Check if a directory is empty (only subdirectories are empty).
 94
 95    Args:
 96    path_to_file (str): The path to the directory to check.
 97
 98    Returns:
 99    bool: True if the directory is empty, False otherwise.
100    """
101    if os.path.isfile(path_to_file):
102        return is_empty_file(path_to_file)
103    contents = os.listdir(path_to_file)
104    for content in contents:
105        path_to_sub = os.path.join(path_to_file, content)
106        if os.path.isfile(path_to_sub):
107            return is_empty_file(path_to_sub)
108        if not os.path.isfile(path_to_sub):
109            is_empty = is_empty_directory_only_subdirectories(path_to_sub)
110            if not is_empty:
111                return False
112    return True
113
114
115def is_empty_file(path_to_file):
116    """
117    Check if a file is empty.
118
119    Args:
120    path_to_file (str): The path to the file to check.
121
122    Returns:
123    bool: True if the file is empty, False otherwise.
124    """
125    if not os.path.isfile(path_to_file):
126        return False
127    if os.path.islink(path_to_file):
128        return False
129    fp_allow_long_path = _get_long_file_path(path_to_file)
130    size = os.path.getsize(fp_allow_long_path)
131    return size == 0
132
133
134def move_file(from_filepath, to_filepath):
135    """
136    Recursively move a file or directory to another location. This is similar to the Unix "mv" command. Return the file or directory's destination.
137
138    If the destination is a directory or a symlink to a directory, the source is moved inside the directory. The destination path must not already exist.
139    """
140    shutil.move(from_filepath, to_filepath)
141
142
143def read_lines_from_file(filepath, skip_comments=False):
144    """
145    Read lines from a text file.
146
147    Args:
148    filepath (str): The path to the text file.
149    skip_comments (bool): Whether to skip lines starting with '#'. Default is False.
150
151    Returns:
152    list: A list of lines read from the file.
153    """
154    lines = []
155    with open(filepath, encoding="utf-8") as file:
156        lines = [line.strip() for line in file]
157    if skip_comments:
158        lines = _remove_comments(lines)
159    return lines
160
161
162def read_text_from_file(filepath):
163    """
164    Read text from a text file.
165
166    Args:
167    filepath (str): The path to the text file.
168
169    Returns:
170    str: The text read from the file.
171    """
172    with open(filepath, encoding="utf-8") as file:
173        return file.read()
174
175
176def _remove_comments(lines):
177    """
178    Remove lines starting with '#' from a list of lines.
179
180    Args:
181    lines (list): List of lines to filter.
182
183    Returns:
184    list: Filtered list of lines without comments.
185    """
186    filtered_lines = []
187    for line in lines:
188        if not line.startswith("#"):
189            filtered_lines.append(line)
190    return filtered_lines
191
192
193def read_text_from_text_or_pdf_file_skipping_comments(filepath):
194    """
195    Read text from a text or PDF file, skipping comments.
196
197    Args:
198    filepath (str): The path to the text or PDF file.
199
200    Returns:
201    str: The text read from the file without comments.
202    """
203    if util_pdf.is_pdf(filepath):
204        return util_pdf.extract_text_from_pdf(filepath)
205    lines = read_lines_from_file(filepath)
206    filtered_lines = _remove_comments(lines)
207    return util_text.LINE_END.join(filtered_lines)
208
209
210def write_text_lines_to_file(lines, filepath):
211    """
212    Write lines of text to a text file.
213
214    Args:
215    lines (list): List of lines to write to the file.
216    filepath (str): The path to the output text file.
217    """
218    with open(filepath, encoding="utf-8", mode="w") as file:
219        for line in lines:
220            file.write(line + util_text.LINE_END)
221
222
223def write_array_to_file_skipping_empty(PATH_TO_OUTPUT_TEXT_FILE, lines):
224    """
225    Write non-empty lines from an array to a file, skipping empty lines.
226
227    Args:
228    PATH_TO_OUTPUT_TEXT_FILE (str): The path to the output text file.
229    lines (list): List of lines to write to the file.
230    """
231    with open(PATH_TO_OUTPUT_TEXT_FILE, "w") as f:
232        for line in lines:
233            if line is not None and len(line) > 0:
234                f.write(line + "\n")
235
236
237def write_text_to_file(text, filepath):
238    """
239    Write text to a text file.
240
241    Args:
242    text (str): The text to write to the file.
243    filepath (str): The path to the output text file.
244    """
245    with open(filepath, "w", encoding="utf-8") as f:
246        f.write(text)
247
248
249def get_last_part_of_path(file_path):
250    """
251    Get the last part of a file path (filename).
252
253    Args:
254    file_path (str): The full file path.
255
256    Returns:
257    str: The last part of the file path (filename).
258    """
259    return file_path.split(os.sep)[-1]
def backup_file_by_copying(path_to_file, backup_dir, backup_filename):
16def backup_file_by_copying(path_to_file, backup_dir, backup_filename):
17    """
18    Backup the given file by copying it to a new uniquely named file.
19    """
20    path_to_backup = os.path.join(backup_dir, backup_filename)
21    path_to_backup = get_unique_filepath(path_to_backup)
22    copy_file(path_to_file, path_to_backup)
23    return path_to_backup

Backup the given file by copying it to a new uniquely named file.

def copy_file(from_path, to_path):
26def copy_file(from_path, to_path):
27    """
28    Copy a file from one path to another.
29
30    Args:
31    from_path (str): The path of the file to copy.
32    to_path (str): The destination path to copy the file to.
33    """
34    shutil.copyfile(from_path, to_path)

Copy a file from one path to another.

Args: from_path (str): The path of the file to copy. to_path (str): The destination path to copy the file to.

def delete_file(path_to_file):
37def delete_file(path_to_file):
38    """
39    Delete a file from the disk.
40    """
41    os.remove(path_to_file)

Delete a file from the disk.

def get_unique_filepath(path_to_file):
44def get_unique_filepath(path_to_file):
45    """
46    Get a unique new filepath, similar to the given path.
47    """
48    filename_no_extension, extension = os.path.splitext(path_to_file)
49
50    suffix = 2
51    while os.path.exists(path_to_file):
52        path_to_file = f"{filename_no_extension}-{suffix:02}{extension}"
53        suffix += 1
54    return path_to_file

Get a unique new filepath, similar to the given path.

def get_this_script_dir(this_file):
57def get_this_script_dir(this_file):
58    """
59    Get the directory of the current script file.
60
61    Args:
62    this_file (str): The path of the current script file (__file__).
63
64    Returns:
65    str: The directory of the current script file.
66    """
67    return os.path.dirname(os.path.realpath(this_file))

Get the directory of the current script file.

Args: this_file (str): The path of the current script file (__file__).

Returns: str: The directory of the current script file.

def is_file_under_dir(path_to_file, path_to_dir):
70def is_file_under_dir(path_to_file, path_to_dir):
71    """
72    Does that file exist under that directory or a sub-directory.
73    """
74    path_to_file = os.path.normpath(path_to_file)
75    path_to_dir = os.path.normpath(path_to_dir) + os.sep
76    return path_to_file.startswith(path_to_dir)

Does that file exist under that directory or a sub-directory.

def is_empty_directory_only_subdirectories(path_to_file):
 92def is_empty_directory_only_subdirectories(path_to_file):
 93    """
 94    Check if a directory is empty (only subdirectories are empty).
 95
 96    Args:
 97    path_to_file (str): The path to the directory to check.
 98
 99    Returns:
100    bool: True if the directory is empty, False otherwise.
101    """
102    if os.path.isfile(path_to_file):
103        return is_empty_file(path_to_file)
104    contents = os.listdir(path_to_file)
105    for content in contents:
106        path_to_sub = os.path.join(path_to_file, content)
107        if os.path.isfile(path_to_sub):
108            return is_empty_file(path_to_sub)
109        if not os.path.isfile(path_to_sub):
110            is_empty = is_empty_directory_only_subdirectories(path_to_sub)
111            if not is_empty:
112                return False
113    return True

Check if a directory is empty (only subdirectories are empty).

Args: path_to_file (str): The path to the directory to check.

Returns: bool: True if the directory is empty, False otherwise.

def is_empty_file(path_to_file):
116def is_empty_file(path_to_file):
117    """
118    Check if a file is empty.
119
120    Args:
121    path_to_file (str): The path to the file to check.
122
123    Returns:
124    bool: True if the file is empty, False otherwise.
125    """
126    if not os.path.isfile(path_to_file):
127        return False
128    if os.path.islink(path_to_file):
129        return False
130    fp_allow_long_path = _get_long_file_path(path_to_file)
131    size = os.path.getsize(fp_allow_long_path)
132    return size == 0

Check if a file is empty.

Args: path_to_file (str): The path to the file to check.

Returns: bool: True if the file is empty, False otherwise.

def move_file(from_filepath, to_filepath):
135def move_file(from_filepath, to_filepath):
136    """
137    Recursively move a file or directory to another location. This is similar to the Unix "mv" command. Return the file or directory's destination.
138
139    If the destination is a directory or a symlink to a directory, the source is moved inside the directory. The destination path must not already exist.
140    """
141    shutil.move(from_filepath, to_filepath)

Recursively move a file or directory to another location. This is similar to the Unix "mv" command. Return the file or directory's destination.

If the destination is a directory or a symlink to a directory, the source is moved inside the directory. The destination path must not already exist.

def read_lines_from_file(filepath, skip_comments=False):
144def read_lines_from_file(filepath, skip_comments=False):
145    """
146    Read lines from a text file.
147
148    Args:
149    filepath (str): The path to the text file.
150    skip_comments (bool): Whether to skip lines starting with '#'. Default is False.
151
152    Returns:
153    list: A list of lines read from the file.
154    """
155    lines = []
156    with open(filepath, encoding="utf-8") as file:
157        lines = [line.strip() for line in file]
158    if skip_comments:
159        lines = _remove_comments(lines)
160    return lines

Read lines from a text file.

Args: filepath (str): The path to the text file. skip_comments (bool): Whether to skip lines starting with '#'. Default is False.

Returns: list: A list of lines read from the file.

def read_text_from_file(filepath):
163def read_text_from_file(filepath):
164    """
165    Read text from a text file.
166
167    Args:
168    filepath (str): The path to the text file.
169
170    Returns:
171    str: The text read from the file.
172    """
173    with open(filepath, encoding="utf-8") as file:
174        return file.read()

Read text from a text file.

Args: filepath (str): The path to the text file.

Returns: str: The text read from the file.

def read_text_from_text_or_pdf_file_skipping_comments(filepath):
194def read_text_from_text_or_pdf_file_skipping_comments(filepath):
195    """
196    Read text from a text or PDF file, skipping comments.
197
198    Args:
199    filepath (str): The path to the text or PDF file.
200
201    Returns:
202    str: The text read from the file without comments.
203    """
204    if util_pdf.is_pdf(filepath):
205        return util_pdf.extract_text_from_pdf(filepath)
206    lines = read_lines_from_file(filepath)
207    filtered_lines = _remove_comments(lines)
208    return util_text.LINE_END.join(filtered_lines)

Read text from a text or PDF file, skipping comments.

Args: filepath (str): The path to the text or PDF file.

Returns: str: The text read from the file without comments.

def write_text_lines_to_file(lines, filepath):
211def write_text_lines_to_file(lines, filepath):
212    """
213    Write lines of text to a text file.
214
215    Args:
216    lines (list): List of lines to write to the file.
217    filepath (str): The path to the output text file.
218    """
219    with open(filepath, encoding="utf-8", mode="w") as file:
220        for line in lines:
221            file.write(line + util_text.LINE_END)

Write lines of text to a text file.

Args: lines (list): List of lines to write to the file. filepath (str): The path to the output text file.

def write_array_to_file_skipping_empty(PATH_TO_OUTPUT_TEXT_FILE, lines):
224def write_array_to_file_skipping_empty(PATH_TO_OUTPUT_TEXT_FILE, lines):
225    """
226    Write non-empty lines from an array to a file, skipping empty lines.
227
228    Args:
229    PATH_TO_OUTPUT_TEXT_FILE (str): The path to the output text file.
230    lines (list): List of lines to write to the file.
231    """
232    with open(PATH_TO_OUTPUT_TEXT_FILE, "w") as f:
233        for line in lines:
234            if line is not None and len(line) > 0:
235                f.write(line + "\n")

Write non-empty lines from an array to a file, skipping empty lines.

Args: PATH_TO_OUTPUT_TEXT_FILE (str): The path to the output text file. lines (list): List of lines to write to the file.

def write_text_to_file(text, filepath):
238def write_text_to_file(text, filepath):
239    """
240    Write text to a text file.
241
242    Args:
243    text (str): The text to write to the file.
244    filepath (str): The path to the output text file.
245    """
246    with open(filepath, "w", encoding="utf-8") as f:
247        f.write(text)

Write text to a text file.

Args: text (str): The text to write to the file. filepath (str): The path to the output text file.

def get_last_part_of_path(file_path):
250def get_last_part_of_path(file_path):
251    """
252    Get the last part of a file path (filename).
253
254    Args:
255    file_path (str): The full file path.
256
257    Returns:
258    str: The last part of the file path (filename).
259    """
260    return file_path.split(os.sep)[-1]

Get the last part of a file path (filename).

Args: file_path (str): The full file path.

Returns: str: The last part of the file path (filename).