1111from .._cache import _check_relative_pathname
1212
1313
14- def path2linux ( path ):
14+ def normalize_pathname ( pathname , sep = "/" , ** kwargs ):
1515 """
16- Converts a path to a standardized Linux file path format for cross-platform compatibility.
16+ Converts a pathname to a consistent file path format for cross-platform compatibility.
1717
18- This function:
18+ This function formats a file (or an OS-specific) path to ensure compatibility across
19+ Windows, Linux and macOS.
1920
20- - Formats the file path to ensure compatibility across Windows, Linux and macOS .
21- - Converts an OS-specific path to a standard Linux path.
22-
23- :param path: Absolute or relative pathname.
24- :type path : str | bytes | os.PathLike
25- :return: Standard Linux pathname .
21+ :param pathname: A pathname .
22+ :type pathname: str | bytes | pathlib.Path | os.PathLike
23+ :param sep: File path separator used by the operating system;
24+ defaults to ``"/"`` (forward slash) for Linux and macOS pathname.
25+ :type sep : str
26+ :return: Pathname of a consistent file path format .
2627 :rtype: str
2728
2829 **Examples**::
2930
30- >>> from pyhelpers.dirs import path2linux
31+ >>> from pyhelpers.dirs import normalize_pathname
32+ >>> import os
3133 >>> import pathlib
32- >>> path2linux ("tests\\ data\\ dat.csv")
34+ >>> normalize_pathname ("tests\\ data\\ dat.csv")
3335 'tests/data/dat.csv'
34- >>> path2linux(pathlib.Path( "tests\\ data\\ dat.csv") )
36+ >>> normalize_pathname( "tests// data/ dat.csv")
3537 'tests/data/dat.csv'
38+ >>> normalize_pathname(pathlib.Path("tests\\ data/dat.csv"), sep=os.path.sep) # On Windows
39+ 'tests\\ data\\ dat.csv'
3640 """
3741
38- # noinspection PyBroadException
39- try :
40- return path .replace ("\\ " , "/" )
41- except Exception :
42- return str (path ).replace ("\\ " , "/" )
43-
44-
45- def uniform_pathname (pathname ):
46- """
47- Converts a pathname to a standard Linux file path format.
48-
49- This function serves as an alternative to :func:`~pyhelpers.dirs.path2linux`.
50-
51- :param pathname: Absolute or relative pathname.
52- :type pathname: str | pathlib.Path
53- :return: Standard Linux pathname.
54- :rtype: str
55-
56- **Examples**::
57-
58- >>> from pyhelpers.dirs import uniform_pathname
59- >>> import pathlib
60- >>> uniform_pathname("tests\\ data\\ dat.csv")
61- 'tests/data/dat.csv'
62- >>> uniform_pathname("tests//data/dat.csv")
63- 'tests/data/dat.csv'
64- >>> uniform_pathname(pathlib.Path("tests\\ data/dat.csv"))
65- 'tests/data/dat.csv'
66- """
42+ if isinstance (pathname , bytes ):
43+ pathname_ = pathname .decode (** kwargs )
44+ else :
45+ pathname_ = str (pathname )
6746
68- pathname_ = re .sub (r"[\\/]+" , "/" , str ( pathname ) )
47+ pathname_ = re .sub (r"[\\/]+" , re . escape ( sep ), pathname_ )
6948
7049 return pathname_
7150
@@ -198,9 +177,9 @@ def validate_filename(file_pathname, suffix_num=1):
198177 >>> from pyhelpers.dirs import validate_filename
199178 >>> import os
200179 >>> test_file_pathname = "tests/data/test.txt"
201- >>> # When the file does not exist, return the same file name
202180 >>> os.path.exists(test_file_pathname)
203181 False
182+ >>> # If the file does not exist, the function returns the same filename
204183 >>> file_pathname_0 = validate_filename(test_file_pathname)
205184 >>> os.path.relpath(file_pathname_0)
206185 'tests\\ data\\ test.txt'
@@ -224,26 +203,26 @@ def validate_filename(file_pathname, suffix_num=1):
224203 ... os.remove(x)
225204 """
226205
227- # convert the path to standard linux path
228- filename_abspath = path2linux ( os .path .abspath (file_pathname ) )
206+ # Convert the path to standard linux path
207+ filename_abspath = os .path .normpath (file_pathname )
229208
230- # get the file suffix
209+ # Get the file suffix
231210 file_suffix = filename_abspath .split ("." )[- 1 ]
232211 file_without_suffix = filename_abspath [:- len (file_suffix ) - 1 ]
233212
234- # remove the suffix if the file name contains "("
213+ # Remove the suffix if the file name contains "("
235214 if "(" in file_without_suffix :
236215 file_without_suffix = file_without_suffix .split ("(" )[0 ]
237216
238- # if the file does not exist, return the same file name
217+ # If the file does not exist, return the same file name
239218 if os .path .exists (filename_abspath ):
240219 filename_update = f"{ file_without_suffix } ({ suffix_num } ).{ file_suffix } "
241220 return validate_filename (filename_update , suffix_num + 1 )
242221
243222 return filename_abspath
244223
245224
246- def get_file_pathnames (path_to_dir , file_ext = None , incl_subdir = False ):
225+ def get_file_pathnames (path_to_dir , file_ext = None , incl_subdir = False , abs_path = False ):
247226 """
248227 Gets paths of files in a directory matching the specified file extension.
249228
@@ -260,52 +239,69 @@ def get_file_pathnames(path_to_dir, file_ext=None, incl_subdir=False):
260239 when ``incl_subdir=True``, it includes files from all subdirectories recursively;
261240 defaults to `False`.
262241 :type incl_subdir: bool
242+ :param abs_path: Whether to return absolute pathname(s).
243+ :type abs_path: bool
263244 :return: List of file paths matching the criteria.
264245 :rtype: list
265246
266247 **Examples**::
267248
268- >>> from pyhelpers.dirs import get_file_pathnames
249+ >>> from pyhelpers.dirs import get_file_pathnames, delete_dir
250+ >>> from pyhelpers.store import unzip
251+ >>> import os
269252 >>> test_dir_name = "tests/data"
270- >>> # Get all files in the folder (without sub-folders)
253+ >>> # Get all files in the directory (without subdirectories) on Windows
271254 >>> get_file_pathnames(test_dir_name)
272- ['tests/data/csr_mat.npz',
273- 'tests/data/dat.csv',
274- 'tests/data/dat.feather',
275- 'tests/data/dat.joblib',
276- 'tests/data/dat.json',
277- 'tests/data/dat.pickle',
278- 'tests/data/dat.txt',
279- 'tests/data/dat.xlsx',
280- 'tests/data/zipped',
281- 'tests/data/zipped.7z',
282- 'tests/data/zipped.txt',
283- 'tests/data/zipped.zip']
255+ ['tests\\ data\\ csr_mat.npz',
256+ 'tests\\ data\\ dat.csv',
257+ 'tests\\ data\\ dat.feather',
258+ 'tests\\ data\\ dat.joblib',
259+ 'tests\\ data\\ dat.json',
260+ 'tests\\ data\\ dat.ods',
261+ 'tests\\ data\\ dat.pickle',
262+ 'tests\\ data\\ dat.pickle.bz2',
263+ 'tests\\ data\\ dat.pickle.gz',
264+ 'tests\\ data\\ dat.pickle.xz',
265+ 'tests\\ data\\ dat.txt',
266+ 'tests\\ data\\ dat.xlsx',
267+ 'tests\\ data\\ zipped.7z',
268+ 'tests\\ data\\ zipped.txt',
269+ 'tests\\ data\\ zipped.zip']
284270 >>> get_file_pathnames(test_dir_name, file_ext=".txt")
285- ['tests/data/dat.txt', 'tests/data/zipped.txt']
271+ ['tests\\ data\\ dat.txt', 'tests\\ data\\ zipped.txt']
272+ >>> output_dir = unzip('tests\\ data\\ zipped.zip', ret_output_dir=True)
273+ >>> os.listdir(output_dir)
274+ ['zipped.txt']
286275 >>> # Get absolute pathnames of all files contained in the folder (incl. all subdirectories)
287- >>> get_file_pathnames(test_dir_name, file_ext="txt", incl_subdir=True)
288- ['tests/data/dat.txt', 'tests/data/zipped.txt', 'tests/data/zipped/zipped.txt']
276+ >>> get_file_pathnames(test_dir_name, file_ext="txt", incl_subdir=True, abs_path=True)
277+ ['<Parent directories>\\ tests\\ data\\ dat.txt',
278+ '<Parent directories>\\ tests\\ data\\ zipped.txt',
279+ '<Parent directories>\\ tests\\ data\\ zipped\\ zipped.txt']
280+ >>> delete_dir(output_dir, confirmation_required=False)
289281 """
290282
291283 if incl_subdir :
292- files_list = []
293- for root , _ , files in os .walk (path_to_dir ):
294- files_list .extend ([os .path .join (root , file ) for file in files ])
284+ file_pathnames = [
285+ os .path .normpath (os .path .join (root , file ))
286+ for root , _ , files in os .walk (path_to_dir )
287+ for file in files
288+ ]
295289
296- if file_ext in {None , "*" , "all" }:
297- return [path2linux (file ) for file in files_list ]
298-
299- return [path2linux (file ) for file in files_list if file .endswith (file_ext )]
290+ else :
291+ file_pathnames = [
292+ os .path .normpath (os .path .join (path_to_dir , file ))
293+ for file in os .listdir (path_to_dir )
294+ if os .path .isfile (os .path .join (path_to_dir , file ))
295+ ]
300296
301- # Files in the first layer of the folder
302297 if file_ext in {None , "*" , "all" }:
303- return [path2linux (os .path .join (path_to_dir , file )) for file in os .listdir (path_to_dir )]
298+ file_pathnames = [
299+ os .path .abspath (p ) if abs_path else p for p in file_pathnames ]
300+ elif file_ext :
301+ file_pathnames = [
302+ os .path .abspath (p ) if abs_path else p for p in file_pathnames if p .endswith (file_ext )]
304303
305- # noinspection PyTypeChecker
306- return [
307- path2linux (os .path .join (path_to_dir , file )) for file in os .listdir (path_to_dir )
308- if file .endswith (file_ext )]
304+ return file_pathnames
309305
310306
311307def check_files_exist (filenames , path_to_dir , verbose = False ):
@@ -326,21 +322,21 @@ def check_files_exist(filenames, path_to_dir, verbose=False):
326322 >>> from pyhelpers.dirs import check_files_exist
327323 >>> test_dir_name = "tests/data"
328324 >>> # Check if all required files exist in the directory
329- >>> check_files_exist(["dat.csv", "dat.txt"], test_dir_name)
325+ >>> check_files_exist(["dat.csv", "dat.txt"], path_to_dir= test_dir_name)
330326 True
331327 >>> # If not all required files exist, print the missing files
332- >>> check_files_exist(("dat.csv", "dat.txt", "dat_0.txt"), test_dir_name)
328+ >>> check_files_exist(("dat.csv", "dat.txt", "dat_0.txt"), test_dir_name, verbose=True )
333329 Error: Required files are not satisfied, missing files are: ['dat_0.txt']
334330 False
335331 """
336332
337333 dir_files = get_file_pathnames (path_to_dir , file_ext = "*" )
338334
339335 # Format the required file name to standard linux path
340- filenames = [path2linux ( os .path .abspath (filename ) ) for filename in filenames ]
336+ file_or_pathnames = [os .path .abspath (filename ) for filename in filenames ]
341337
342- required_files_short = [filename .split ("/" )[- 1 ] for filename in filenames ]
343- dir_files_short = [filename .split ("/" )[- 1 ] for filename in dir_files ]
338+ required_files_short = [filename .split (os . path . sep )[- 1 ] for filename in file_or_pathnames ]
339+ dir_files_short = [filename .split (os . path . sep )[- 1 ] for filename in dir_files ]
344340
345341 # `mask` have the same length as `filenames`
346342 mask = [file in dir_files_short for file in required_files_short ]
0 commit comments