-
Notifications
You must be signed in to change notification settings - Fork 32
/
file_utils.py
170 lines (139 loc) · 6.43 KB
/
file_utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
import filecmp
import os
import shutil
import tempfile
from inspect import currentframe, getframeinfo
from pathlib import Path
# return the itens in array that is not inexisting or empty
def validate_files(paths):
valid_files = [path for path in paths if file_is_valid(path)]
return valid_files
# check if a file is existing and not empty
def file_is_valid(path):
if path is not None and path.is_file():
size = path.stat().st_size
if size > 0:
return True
return False
# validate if an string is a valid dir or path with valid content
def check_valid_path(path_str):
# create a Path object from the input string
path = Path(path_str)
# check if the path exists
if not path.exists():
raise FileNotFoundError(f"The path '{path_str}' does not exist.")
# check if it's a directory with at least one file or a valid file with content
if path.is_dir():
# check if the directory has at least one file with content
files_with_content = [file for file in path.iterdir() if file.is_file() and file.stat().st_size > 0]
if not files_with_content:
raise ValueError(f"The directory '{path_str}' does not contain any files with content.")
elif path.is_file():
# check if the file has content
if path.stat().st_size == 0:
raise ValueError(f"The file '{path_str}' does not contain any content.")
else:
raise ValueError(f"The path '{path_str}' is neither a valid directory nor a valid file.")
return path
# validate if an string is a valid dir or path with valid content
def check_existing_path(path_str):
# create a Path object from the input string
path = Path(path_str)
# check if the path exists
if not path.exists():
raise FileNotFoundError(f"The path '{path_str}' does not exist.")
# check if it's a directory with at least one file or a valid file with content
if not path.is_dir() and not path.is_file():
raise ValueError(f"The path '{path_str}' is neither a valid directory nor a valid file.")
return path_str
# create a tempfile class to use as object
class TempFile:
def __init__(self, final_path: Path, file_ext: str = None):
self.final_path: Path = None if final_path is None else Path(
final_path)
self.file_ext = file_ext
os.makedirs(Path(Path(getframeinfo(
currentframe()).filename).resolve().parent, "temp"), exist_ok=True)
self.temp_file: tempfile.NamedTemporaryFile = tempfile.NamedTemporaryFile(dir=Path(Path(getframeinfo(currentframe()).filename).resolve().parent, "temp"),
delete=False, suffix=file_ext)
self.temp_file_name = self.temp_file.name
self.temp_file_path: Path = Path(self.temp_file.name)
self.temp_file.close()
# return the actual path of the file
def getpath(self):
if self.temp_file_path.is_file():
return self.temp_file_path
elif file_is_valid(self.final_path):
return self.final_path
else:
return None
# return the actual path of the file if not empty
def getvalidpath(self):
if file_is_valid(self.temp_file_path):
return self.temp_file_path
elif file_is_valid(self.final_path):
return self.final_path
else:
return None
# save the temp file into final path
def save(self, overwrite_if_valid: bool = True, update_path: Path = None):
# update final path case user specifies it
if update_path is None:
path: Path = self.final_path
else:
path: Path = update_path
try:
# if file not valid ou overwrite is enabled, move overwiting existing file
if not file_is_valid(self.final_path) or overwrite_if_valid:
os.makedirs(path.parent, exist_ok=True)
shutil.move(self.temp_file_path, path)
self.final_path = path
except Exception as e:
print(f"Error saving file: {e}")
return
# delete the file
def destroy(self):
try:
# destroy temporary file if it exists
if file_is_valid(self.temp_file_path):
os.remove(self.temp_file_path)
except Exception:
return
# copy an source file to destination if destination file is not equals to source
def copy_file_if_different(src_file: Path, dst_file: Path, silent: bool = False):
if file_is_valid(dst_file):
# Check if destination file exists and is different from source file
if filecmp.cmp(src_file, dst_file) and not silent:
print(f"{dst_file} already exists and is the same. No need to copy.")
return
os.makedirs(dst_file.parent, exist_ok=True)
shutil.copyfile(src_file, dst_file)
if not silent:
print(f"copied to {dst_file}")
# function to delete dir and all its content using shutil
def delete_folder(path: Path):
if path.is_dir():
shutil.rmtree(path)
def update_folder_times(folder_path):
folder_path = Path(folder_path)
# Keep track of the newest file's modification time for this folder
newest_file_time = None
for item in folder_path.iterdir():
# Check if the item is a file
if item.is_file():
file_time = item.stat().st_mtime # Get modification time of the file
# Update the newest_file_time if it's the first file or if the current file is newer
if newest_file_time is None or file_time > newest_file_time:
newest_file_time = file_time
# If the item is a subfolder, recursively update its times and find its newest file time
elif item.is_dir():
subfolder_newest_time = update_folder_times(item)
# Update the newest_file_time if a subfolder's newest file is newer
if newest_file_time is None or (subfolder_newest_time is not None and subfolder_newest_time > newest_file_time):
newest_file_time = subfolder_newest_time
# Update the folder's modification and creation times with the newest_file_time
if newest_file_time is not None:
# Convert to an integer (necessary on some systems)
newest_file_time = int(newest_file_time)
os.utime(path=folder_path, times=(newest_file_time, newest_file_time))
return newest_file_time # Return the newest_file_time to update the parent folder's time