Getting a list of all subdirectories in the current directory
Получение списка всех подкаталогов в текущем каталоге
Есть ли способ вернуть список всех подкаталогов в текущем каталоге в Python?
Я знаю, что вы можете сделать это с файлами, но вместо этого мне нужно получить список каталогов.
Переведено автоматически
Ответ 1
Вы имеете в виду непосредственные подкаталоги или каждый каталог прямо по дереву?
В любом случае, вы могли бы использовать os.walk для этого:
os.walk(directory)
выдаст кортеж для каждого подкаталога. Первая запись в 3-м кортеже - это имя каталога, поэтому
[x[0] for x in os.walk(directory)]
должно предоставить вам все подкаталоги рекурсивно.
Обратите внимание, что вторая запись в кортеже - это список дочерних каталогов записи на первой позиции, поэтому вы могли бы использовать это вместо, но вряд ли это сильно сэкономит вам.
Однако вы могли бы использовать его только для предоставления вам непосредственных дочерних каталогов:
from glob import glob glob("/path/to/directory/*/", recursive = True)
Не забудьте о конце / после *.
Ответ 3
Намного приятнее, чем вышеописанное, потому что вам не нужно несколько os.path.join() и вы получите полный путь напрямую (при желании), вы можете сделать это в Python 3.5 и выше.
subfolders = [ f.path for f in os.scandir(folder) if f.is_dir() ]
Это даст полный путь к подкаталогу. Если вам нужно только название подкаталога, используйте f.name вместо f.path
Немного О том, что: в случае, если вам нужны все вложенные папки рекурсивно и / или все файлы рекурсивно, взгляните на эту функцию, которая быстрее, чем os.walk & glob и вернет список всех вложенных папок, а также всех файлов внутри этих (вложенных)папок: https://pythonly.ru/a/59803793/2441026
На случай, если вам нужны только все вложенные папки рекурсивно:
deffast_scandir(dirname): subfolders= [f.path for f in os.scandir(dirname) if f.is_dir()] for dirname inlist(subfolders): subfolders.extend(fast_scandir(dirname)) return subfolders
Возвращает список всех вложенных папок с их полными путями. Это снова быстрее, чем os.walk и намного быстрее, чем glob.
Анализ всех функций
tl; dr: - Если вы хотите получить все непосредственные подкаталоги для папки , используйте os.scandir. - Если вы хотите получить все подкаталоги, даже вложенные, используйте os.walk или - немного быстрее - fast_scandir функцию выше. - Никогда не используйте os.walk только для подкаталогов верхнего уровня, так как это может быть в сотни (!) раз медленнее, чем os.scandir.
Если вы запустите приведенный ниже код, обязательно запустите его один раз, чтобы ваша операционная система получила доступ к папке, отмените результаты и запустите тест, в противном случае результаты будут испорчены.
Возможно, вы захотите перепутать вызовы функций, но я протестировал это, и это действительно не имело значения.
Во всех примерах будет указан полный путь к папке. Пример pathlib в виде объекта Path (Windows).
Первым элементом os.walk будет базовая папка. Таким образом, вы получите не только подкаталоги. Вы можете использовать fu.pop(0), чтобы удалить его.
Ни в одном из результатов не будет использоваться естественная сортировка. Это означает, что результаты будут отсортированы следующим образом: 1, 10, 2. Чтобы получить естественную сортировку (1, 2, 10), пожалуйста, взгляните на https://pythonly.ru/a/48030307/2441026
Результаты:
os.scandir took 1 ms. Found dirs: 439 os.walk took 463 ms. Found dirs: 441 -> it found the nested one + base folder. glob.glob took 20 ms. Found dirs: 439 pathlib.iterdir took 18 ms. Found dirs: 439 os.listdir took 18 ms. Found dirs: 439
Протестировано с W7x64, Python 3.8.1.
# -*- coding: utf-8 -*- # Python 3
import time import os from glob import glob from pathlib import Path
directory = r"<insert_folder>" RUNS = 1
defrun_os_walk(): a = time.time_ns() for i inrange(RUNS): fu = [x[0] for x in os.walk(directory)] print(f"os.walk\t\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
defrun_glob(): a = time.time_ns() for i inrange(RUNS): fu = glob(directory + "/*/") print(f"glob.glob\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
defrun_pathlib_iterdir(): a = time.time_ns() for i inrange(RUNS): dirname = Path(directory) fu = [f for f in dirname.iterdir() if f.is_dir()] print(f"pathlib.iterdir\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
defrun_os_listdir(): a = time.time_ns() for i inrange(RUNS): dirname = Path(directory) fu = [os.path.join(directory, o) for o in os.listdir(directory) if os.path.isdir(os.path.join(directory, o))] print(f"os.listdir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
defrun_os_scandir(): a = time.time_ns() for i inrange(RUNS): fu = [f.path for f in os.scandir(directory) if f.is_dir()] print(f"os.scandir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms.\tFound dirs: {len(fu)}")
if __name__ == '__main__': run_os_scandir() run_os_walk() run_glob() run_pathlib_iterdir() run_os_listdir()
Ответ 4
import os
d = '.' [os.path.join(d, o) for o in os.listdir(d) if os.path.isdir(os.path.join(d,o))]