import os def get_immediate_subdirectories(a_dir): return [name for name in os.listdir(a_dir) if os.path.isdir(os.path.join(a_dir, name))]
ID : 20345
viewed : 23
94
import os def get_immediate_subdirectories(a_dir): return [name for name in os.listdir(a_dir) if os.path.isdir(os.path.join(a_dir, name))]
90
I did some speed testing on various functions to return the full path to all current subdirectories.
tl;dr: Always use scandir
:
list_subfolders_with_paths = [f.path for f in os.scandir(path) if f.is_dir()]
Bonus: With scandir
you can also simply only get folder names by using f.name
instead of f.path
.
This (as well as all other functions below) will not use natural sorting. This means results will be sorted like this: 1, 10, 2. To get natural sorting (1, 2, 10), please have a look at https://stackoverflow.com/a/48030307/2441026
Results: scandir
is: 3x faster than walk
, 32x faster than listdir
(with filter), 35x faster than Pathlib
and 36x faster than listdir
and 37x (!) faster than glob
.
Scandir: 0.977 Walk: 3.011 Listdir (filter): 31.288 Pathlib: 34.075 Listdir: 35.501 Glob: 36.277
Tested with W7x64, Python 3.8.1. Folder with 440 subfolders.
In case you wonder if listdir
could be speed up by not doing os.path.join() twice, yes, but the difference is basically nonexistent.
Code:
import os import pathlib import timeit import glob path = r"<example_path>" def a(): list_subfolders_with_paths = [f.path for f in os.scandir(path) if f.is_dir()] # print(len(list_subfolders_with_paths)) def b(): list_subfolders_with_paths = [os.path.join(path, f) for f in os.listdir(path) if os.path.isdir(os.path.join(path, f))] # print(len(list_subfolders_with_paths)) def c(): list_subfolders_with_paths = [] for root, dirs, files in os.walk(path): for dir in dirs: list_subfolders_with_paths.append( os.path.join(root, dir) ) break # print(len(list_subfolders_with_paths)) def d(): list_subfolders_with_paths = glob.glob(path + '/*/') # print(len(list_subfolders_with_paths)) def e(): list_subfolders_with_paths = list(filter(os.path.isdir, [os.path.join(path, f) for f in os.listdir(path)])) # print(len(list(list_subfolders_with_paths))) def f(): p = pathlib.Path(path) list_subfolders_with_paths = [x for x in p.iterdir() if x.is_dir()] # print(len(list_subfolders_with_paths)) print(f"Scandir: {timeit.timeit(a, number=1000):.3f}") print(f"Listdir: {timeit.timeit(b, number=1000):.3f}") print(f"Walk: {timeit.timeit(c, number=1000):.3f}") print(f"Glob: {timeit.timeit(d, number=1000):.3f}") print(f"Listdir (filter): {timeit.timeit(e, number=1000):.3f}") print(f"Pathlib: {timeit.timeit(f, number=1000):.3f}")
71
Why has no one mentioned glob
? glob
lets you use Unix-style pathname expansion, and is my go to function for almost everything that needs to find more than one path name. It makes it very easy:
from glob import glob paths = glob('*/')
Note that glob
will return the directory with the final slash (as unix would) while most path
based solutions will omit the final slash.
60
Check "Getting a list of all subdirectories in the current directory".
Here's a Python 3 version:
import os dir_list = next(os.walk('.'))[1] print(dir_list)
57
import os
To get (full-path) immediate sub-directories in a directory:
def SubDirPath (d): return filter(os.path.isdir, [os.path.join(d,f) for f in os.listdir(d)])
To get the latest (newest) sub-directory:
def LatestDirectory (d): return max(SubDirPath(d), key=os.path.getmtime)