"""
File Utilities
==============
This module provides functions for working with files and folders, including
file search, text replacement, and file and folder deletion.
"""
import os
from typing import List
import shutil
[docs]
def get_filenames_in_folder(folder_path: str) -> List[str]:
"""
Get the filenames in the specified folder.
Parameters
----------
folder_path : str
The path of the folder.
Returns
-------
List[str]
A list of filenames in the folder.
Examples
--------
>>> folder_path = 'path/to/your/folder'
>>> filenames = get_filenames_in_folder(folder_path)
>>> for filename in filenames:
... print(filename)
"""
filenames = []
for file in os.listdir(folder_path):
if os.path.isfile(os.path.join(folder_path, file)):
filenames.append(file)
return filenames
[docs]
def get_foldernames_in_folder(folder_path: str) -> List[str]:
"""
Get the folders in the specified folder.
Parameters
----------
folder_path : str
The path of the folder.
Returns
-------
List[str]
A list of folders in the folder.
Examples
--------
>>> folder_path = 'path/to/your/folder'
>>> folders = get_foldernames_in_folder(folder_path)
>>> for folder_name in folders:
... print(folder_name)
"""
folders = []
for item in os.listdir(folder_path):
if os.path.isdir(os.path.join(folder_path, item)):
folders.append(item)
return folders
[docs]
def find_files_with_extension(folder_path: str, extension: str) -> List[str]:
"""
Find files with the specified extension in the given folder.
Parameters
----------
folder_path : str
The path of the folder.
extension : str
The file extension to search for.
Returns
-------
List[str]
A list of file paths with the matching extension.
Examples
--------
>>> folder_path = 'path/to/your/folder'
>>> extension = '.txt'
>>> files_with_extension = find_files_with_extension(folder_path, extension)
>>> for file_path in files_with_extension:
... print(file_path)
"""
matching_files = []
# Use os.walk to iterate through the folder structure
for root, _, files in os.walk(folder_path):
for file in files:
if file.endswith(extension):
# Construct the full path of the file
matching_files.append(os.path.join(root, file))
return sorted(matching_files)
[docs]
def read_last_line(file_path):
"""
Read the last line of a specified file.
Parameters
----------
file_path : str
The path to the file to be read.
Returns
-------
str or None
The last line of the file as a string, stripped of leading and trailing
whitespace.
Returns None if the file is empty.
Examples
--------
>>> file_path = 'path/to/your/file.txt'
>>> last_line = read_last_line(file_path)
>>> if last_line is not None:
... print("Last line:", last_line)
... else:
... print("The file is empty.")
"""
with open(file_path, 'r') as file:
lines = file.readlines()
if lines:
return lines[-1].strip()
else:
return None
[docs]
def read_last_lines(file_path, num_lines):
"""
Read the specified number of lines from the end of a file.
Parameters
----------
file_path : str
The path to the file to be read.
num_lines : int
The number of lines to read from the end of the file.
Returns
-------
list
A list of strings representing the last `num_lines` lines of the file.
If the file has fewer lines than `num_lines`, it will return all
available lines.
Examples
--------
>>> file_path = 'path/to/your/file.txt'
>>> num_lines = 5
>>> last_lines = read_last_lines(file_path, num_lines)
>>> for line in last_lines:
... print(line)
"""
with open(file_path, 'r') as file:
lines = file.readlines()
last_lines = lines[-num_lines:]
return [line.strip() for line in last_lines]
[docs]
def replace_text(original, target, list_replace):
"""
Replaces specified patterns with corresponding strings in a file.
Parameters
----------
original : str
Path to the original file.
target : str
Path to the target file where the modified content will be saved.
list_replace : list
List of tuples, where each tuple contains the pattern to be replaced
and its corresponding string.
Returns
-------
bool
True if the text is replaced successfully, False otherwise.
Examples
--------
>>> original_file = "path/to/original/file.txt"
>>> target_file = "path/to/target/file.txt"
>>> replacements = [
... ("pattern1", "replacement1"),
... ("pattern2", "replacement2"),
... ("pattern3", "replacement3")
... ]
>>> success = replace_text(original_file, target_file, replacements)
>>> if success:
... print("Text replacement successful.")
... else:
... print("Text replacement failed.")
"""
try:
# Copying the original file to the target file
shutil.copyfile(original, target)
# Opening the target file in read and write mode
with open(target, 'r+') as file:
# Reading the file data and storing it in a variable
file_data = file.read()
# Replacing the patterns with the strings in the file data
for pattern, replacement in list_replace:
file_data = file_data.replace(pattern, replacement)
# Setting the position to the top of the file to overwrite data
file.seek(0)
# Writing the replaced data in the file
file.write(file_data)
# Truncating the file to remove any extra content
file.truncate()
# Return True to indicate successful text replacement
return True
except Exception as e:
print(f"An error occurred while replacing text: {e}")
return False
[docs]
def delete_specific_files(folder_path, extensions):
"""
Delete files with specific extensions from a given folder.
This function iterates through all the files in the given folder and deletes
files with extensions specified in the 'extensions' list.
Parameters
----------
folder_path : str
Path to the folder containing the files.
extensions : list of str
List of file extensions to be deleted.
Returns
-------
None
The function does not return any value.
Raises
------
Exception
If an error occurs while deleting the files.
Example
-------
folder_path = "/path/to/folder"
extensions_to_delete = ['.log', '.conv', '.h5', '.xdmf']
delete_specific_files(folder_path, extensions_to_delete)
"""
try:
for filename in os.listdir(folder_path):
file_path = os.path.join(folder_path, filename)
if os.path.isfile(file_path):
file_extension = os.path.splitext(filename)[1]
if file_extension in extensions:
os.remove(file_path)
print(f"Deleted: {file_path}")
print("All specified files deleted successfully.")
except Exception as e:
print(f"An error occurred: {e}")
[docs]
def delete_folders_with_contents(folder_path, folder_names):
"""
Delete specified folders and their contents from a given folder.
This function iterates through the specified folder names and deletes the
corresponding folders along with their contents from the given folder.
Parameters
----------
folder_path : str
Path to the folder containing the folders to be deleted.
folder_names : list of str
List of folder names to be deleted.
Returns
-------
None
The function does not return any value.
Raises
------
Exception
If an error occurs while deleting the folders.
Example
-------
folder_path = "/path/to/folder"
folder_names = ["folder_to_delete_1", "folder_to_delete_2"]
delete_folders_with_contents(folder_path, folder_names)
"""
try:
for folder_name in folder_names:
target_folder_path = os.path.join(folder_path, folder_name)
if os.path.exists(target_folder_path) and os.path.isdir(
target_folder_path):
shutil.rmtree(target_folder_path)
print(f"Deleted folder and its contents: {target_folder_path}")
print("All specified folders and their contents deleted successfully.")
except Exception as e:
print(f"An error occurred: {e}")
[docs]
def prepare_simulation(path, results_folder_name="results"):
"""
Prepare simulation directory by deleting specific files and folders.
This function prepares a simulation directory by deleting specific files and
folders that are commonly generated during simulations and creates a folder
with the specified name.
Parameters
----------
path : str
Path to the simulation directory.
results_folder_name : str, optional
Name of the folder to be created. Default is "results".
Returns
-------
None
The function does not return any value.
Example
-------
folder_path = "/path/to/simulation"
prepare_simulation(folder_path, "my_results")
"""
extensions_to_delete = ['.log',
'.conv',
'.h5',
'.xdmf',
'.energy',
'.reaction',
'.dof']
delete_specific_files(path, extensions_to_delete)
delete_folders_with_contents(path, ["paraview-solutions"])
results_path = os.path.join(path, results_folder_name)
delete_folders_with_contents(path, [results_path])
os.makedirs(results_path)
[docs]
def delete_folder(folder_path):
"""
Recursively deletes a folder and its contents.
Parameters
----------
folder_path : str
The path to the folder to be deleted.
Raises
------
OSError
If an error occurs during the deletion process.
Notes
-----
This function iterates over all items in the specified folder, removing files
and recursively calling itself for subdirectories. Finally, it removes the
empty folder.
Examples
--------
>>> delete_folder('/path/to/your/folder')
Folder '/path/to/your/folder' and its contents deleted successfully.
"""
try:
# Iterate over all the items in the folder
for item in os.listdir(folder_path):
item_path = os.path.join(folder_path, item)
# If it's a file, remove it
if os.path.isfile(item_path):
os.remove(item_path)
# If it's a directory, recursively call the function
elif os.path.isdir(item_path):
delete_folder(item_path)
# Finally, remove the empty folder
os.rmdir(folder_path)
print(f"Folder '{folder_path}' and its contents deleted successfully.")
except Exception as e:
print(f"Error: {e}")
[docs]
def append_results_to_file(output_file_path, header, step, *data):
"""
Appends results to a specified file, including a header if the file is empty.
Parameters
----------
output_file_path : str
The path to the file where results will be appended.
header : str
The header line to write if the file is empty.
step : int or str
The step number or identifier to write at the beginning of the line.
*data : tuple
Variable length argument list containing the data to append, which will be tab-separated.
Notes
-----
- If the file specified by `output_file_path` is empty, the `header` will be written first.
- Each subsequent call will append a new line with the `step` and `data` values.
Examples
--------
>>> append_results_to_file('results.txt', 'Time\tValue1\tValue2', 1, 0.5, 1.2)
>>> append_results_to_file('results.txt', 'Time\tValue1\tValue2', 2, 0.6, 1.3)
"""
with open(output_file_path, 'a') as file:
if os.path.getsize(output_file_path) == 0:
file.write(f'{header}\n')
data_str = '\t'.join(str(d) for d in data)
line = f'{step}\t{data_str}\n'
file.write(line)