Skip to content

Commit 676a051

Browse files
authored
Merge pull request #116 from lguerard/listdir_matching_recursive
feat(pathtools): add recursive option to listdir_matching
2 parents 0ecc329 + e730026 commit 676a051

1 file changed

Lines changed: 54 additions & 12 deletions

File tree

src/imcflibs/pathtools.py

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,9 @@ def jython_fiji_exists(path):
180180
return False
181181

182182

183-
def listdir_matching(path, suffix, fullpath=False, sort=False, regex=False):
183+
def listdir_matching(
184+
path, suffix, fullpath=False, sort=False, regex=False, recursive=False
185+
):
184186
"""Get a list of files in a directory matching a given suffix.
185187
186188
Parameters
@@ -199,25 +201,65 @@ def listdir_matching(path, suffix, fullpath=False, sort=False, regex=False):
199201
regex : bool, optional
200202
If set to True, uses the suffix-string as regular expression to match
201203
filenames. By default False.
204+
recursive : bool, optional
205+
If set to True, the directory tree will be traversed recursively and
206+
files in subfolders will be included. When `fullpath` is False and
207+
`recursive` is True the returned file names are relative to `path`
208+
(e.g. `subdir/file.ext`). Default is False.
202209
203210
Returns
204211
-------
205212
list
206213
All file names in the directory matching the suffix (without path!).
207214
"""
208215
matching_files = list()
209-
for candidate in os.listdir(path):
210-
if not regex and candidate.lower().endswith(suffix.lower()):
211-
# log.debug("Found file %s", candidate)
212-
if fullpath:
213-
matching_files.append(os.path.join(path, candidate))
214-
else:
215-
matching_files.append(candidate)
216-
if regex and re.match(suffix.lower(), candidate.lower()):
217-
if fullpath:
218-
matching_files.append(os.path.join(path, candidate))
216+
217+
# Prepare regex if requested (case-insensitive)
218+
regex_compiled = None
219+
if regex:
220+
try:
221+
regex_compiled = re.compile(suffix, re.IGNORECASE)
222+
except re.error:
223+
# If provided regex is invalid, fall back to no matches
224+
return matching_files
225+
226+
if recursive:
227+
# Walk directory tree and test each filename
228+
for dirpath, _, filenames in os.walk(path):
229+
for candidate in filenames:
230+
if not regex_compiled:
231+
if candidate.lower().endswith(suffix.lower()):
232+
if fullpath:
233+
matching_files.append(os.path.join(dirpath, candidate))
234+
else:
235+
rel = os.path.relpath(
236+
os.path.join(dirpath, candidate), path
237+
)
238+
matching_files.append(rel)
239+
else:
240+
if regex_compiled.match(candidate):
241+
if fullpath:
242+
matching_files.append(os.path.join(dirpath, candidate))
243+
else:
244+
rel = os.path.relpath(
245+
os.path.join(dirpath, candidate), path
246+
)
247+
matching_files.append(rel)
248+
else:
249+
# Non-recursive: only list entries in the given directory
250+
for candidate in os.listdir(path):
251+
if not regex_compiled:
252+
if candidate.lower().endswith(suffix.lower()):
253+
if fullpath:
254+
matching_files.append(os.path.join(path, candidate))
255+
else:
256+
matching_files.append(candidate)
219257
else:
220-
matching_files.append(candidate)
258+
if regex_compiled.match(candidate):
259+
if fullpath:
260+
matching_files.append(os.path.join(path, candidate))
261+
else:
262+
matching_files.append(candidate)
221263

222264
if sort:
223265
matching_files = strtools.sort_alphanumerically(matching_files)

0 commit comments

Comments
 (0)