Есть ли способ вернуть список всех подкаталогов в текущем каталоге в Python?
Я знаю, что вы можете делать это с файлами, но вместо этого мне нужно получить список каталогов.
Есть ли способ вернуть список всех подкаталогов в текущем каталоге в Python?
Я знаю, что вы можете делать это с файлами, но вместо этого мне нужно получить список каталогов.
Вы имеете в виду непосредственные подкаталоги или каждый каталог прямо в дереве?
В любом случае для этого можно использовать os.walk
:
os.walk(directory)
даст кортеж для каждого подкаталога. Первая запись в 3-кортеже - это имя каталога, поэтому
[x[0] for x in os.walk(directory)]
должен рекурсивно предоставить вам все подкаталоги.
Обратите внимание, что вторая запись в кортеже - это список дочерних каталогов записи в первой позиции, поэтому вы можете использовать это вместо этого, но это вряд ли вас сильно сэкономит.
Однако вы можете использовать его только для непосредственного предоставления дочерних каталогов:
next(os.walk('.'))[1]
Или просмотрите другие уже опубликованные решения, используя os.listdir
и _ 6_, в том числе на "Как получить все непосредственные подкаталоги в Python ".
os.walk
и _2 _ + _ 3_: я только что протестировал каталог с 10 000 подкаталогов (с миллионами файлов в иерархии ниже), и различия в производительности незначительны. os.walk
: 10 циклов, лучшее из 3: 44,6 мс на цикл и _5 _ + _ 6_: 10 циклов, лучшее из 3: 45,1 мс на цикл
- person kevinmicke; 28.02.2017
Вы можете просто использовать glob.glob
from glob import glob
glob("/path/to/directory/*/")
Не забывайте конечный /
после *
.
/
в именах
- person juanmirocks; 21.03.2018
/
разделителем папок, сделайте следующее: glob(os.path.join(path_to_directory, "*", ""))
- person juanmirocks; 21.03.2018
recursive=True
- person JacoSolari; 12.11.2019
Намного лучше, чем указано выше, потому что вам не нужно несколько os.path.join (), и вы получите полный путь напрямую (если хотите), вы можете сделать это в Python 3.5 и выше. .
subfolders = [ f.path for f in os.scandir(folder) if f.is_dir() ]
Это даст полный путь к подкаталогу. Если вам нужно только имя подкаталога, используйте f.name
вместо f.path
https://docs.python.org/3/library/os.html#os.scandir
Слегка ОТ: если вам нужно рекурсивно все подпапки и / или все файлы рекурсивно, взгляните на эту функцию, которая быстрее, чем os.walk
& glob
, и вернет список всех вложенных папок, а также всех файлов внутри этих (вложенных) вложенных папок: https://stackoverflow.com/a/59803793/2441026 < / а>
Если вы хотите рекурсивно только все подпапки:
def fast_scandir(dirname):
subfolders= [f.path for f in os.scandir(dirname) if f.is_dir()]
for dirname in list(subfolders):
subfolders.extend(fast_scandir(dirname))
return subfolders
Возвращает список всех вложенных папок с их полными путями. Это снова быстрее, чем os.walk
, и намного быстрее, чем glob
.
Анализ всех функций
tl; dr:
- Если вы хотите получить все подкаталоги немедленно для папки, используйте os.scandir
.
- Если вы хотите получить все подкаталоги, даже < em> вложенные, используйте os.walk
или - немного быстрее - указанную выше функцию fast_scandir
.
- Никогда не используйте os.walk
только для подкаталогов верхнего уровня, так как это может быть в сотни (!) раз медленнее, чем os.scandir
.
os.walk
будет базовой папкой. Таким образом, вы не получите только подкаталоги. Вы можете использовать fu.pop(0)
, чтобы удалить его.Результаты:
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
def run_os_walk():
a = time.time_ns()
for i in range(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)}")
def run_glob():
a = time.time_ns()
for i in range(RUNS):
fu = glob(directory + "/*/")
print(f"glob.glob\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_pathlib_iterdir():
a = time.time_ns()
for i in range(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)}")
def run_os_listdir():
a = time.time_ns()
for i in range(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)}")
def run_os_scandir():
a = time.time_ns()
for i in range(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()
using
pathlib` следующим образом `[f for f in p.iterdir () if f.is_dir ()]` `
- person Charlie Parker; 20.07.2020
fast_scandir
, и это занимает больше часа. Это нормально? Могу ли я что-нибудь сделать, чтобы это ускорить?
- person Vincent; 18.08.2020
Если вам нужно рекурсивное решение, которое найдет все подкаталоги в подкаталогах, используйте walk, как предлагалось ранее.
Если вам нужны только дочерние каталоги текущего каталога, объедините os.listdir
с os.path.isdir
pathlib
проще: [f for f in p.iterdir() if f.is_dir()]
- person Charlie Parker; 20.07.2020
pathlib
.
- person Eli Bendersky; 20.07.2020
Python 3.4 представил модуль pathlib
в стандартной библиотеке, которая обеспечивает объектно-ориентированную подход к обработке путей файловой системы:
from pathlib import Path
p = Path('./')
# All subdirectories in the current directory, not recursive.
[f for f in p.iterdir() if f.is_dir()]
Чтобы рекурсивно перечислить все подкаталоги, можно использовать подстановку пути с шаблоном **
.
# This will also include the current directory '.'
list(p.glob('**'))
Обратите внимание, что один *
в качестве шаблона глобуса будет включать и файлы, и каталоги нерекурсивно. Чтобы получить только каталоги, можно добавить завершающий /
, но это работает только при прямом использовании библиотеки glob, а не при использовании glob через pathlib:
import glob
# These three lines return both files and directories
list(p.glob('*'))
list(p.glob('*/'))
glob.glob('*')
# Whereas this returns only directories
glob.glob('*/')
Таким образом, Path('./').glob('**')
соответствует тем же путям, что и glob.glob('**/', recursive=True)
.
Pathlib также доступен в Python 2.7 через модуль pathlib2 в PyPi.
for f in filter(Path.is_dir, p.iterdir()):
- person Bryan Roach; 26.10.2019
gloab(*/)
недостаточно? Тем не менее, потрясающий ответ, особенно для вашего чистого использования pathlib
. Было бы неплохо прокомментировать, если он также допускает рекурсию, хотя из заголовка вопроса, который не нужен, и будущие читатели должны прочитать документы, на которые вы ссылаетесь.
- person Charlie Parker; 20.07.2020
**
с глобусом pathlib. Что касается использования одной звездочки, это будет соответствовать файлам и каталогам нерекурсивно.
- person joelostblom; 20.07.2020
glob.glob('**/', recursive=True)
не будет включать скрытые каталоги, но Path('./').glob('**')
включает
- person nos; 05.07.2021
Я предпочитаю использовать фильтр (https://docs.python.org/2/library/functions.html#filter), но это дело вкуса.
d='.'
filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d))
pathlib
проще: [f for f in p.iterdir() if f.is_dir()]
- person Charlie Parker; 20.07.2020
Реализовано это с помощью python-os-walk. (http://www.pythonforbeginners.com/code-snippets-source-code/python-os-walk/).
import os
print("root prints out directories only from what you specified")
print("dirs prints out sub-directories from root")
print("files prints out all files from root and directories")
print("*" * 20)
for root, dirs, files in os.walk("/var/log"):
print(root)
print(dirs)
print(files)
pathlib
проще: [f for f in p.iterdir() if f.is_dir()]
- person Charlie Parker; 20.07.2020
print("\nWe are listing out only the directories in current directory -")
directories_in_curdir = filter(os.path.isdir, os.listdir(os.curdir))
print(directories_in_curdir)
files = filter(os.path.isfile, os.listdir(os.curdir))
print("\nThe following are the list of all files in the current directory -")
print(files)
Вы можете получить список подкаталогов (и файлов) в Python 2.7, используя os.listdir (путь)
import os
os.listdir(path) # list of subdirectories and files
os.listdir
перечисляет содержимое каталога, включая файлы.
- person guneysus; 26.10.2016
Поскольку я наткнулся на эту проблему, используя пути Python 3.4 и Windows UNC, вот вариант для этой среды:
from pathlib import WindowsPath
def SubDirPath (d):
return [f for f in d.iterdir() if f.is_dir()]
subdirs = SubDirPath(WindowsPath(r'\\file01.acme.local\home$'))
print(subdirs)
Pathlib впервые появился в Python 3.4 и значительно упрощает работу с путями в разных операционных системах: https://docs.python.org/3.4/library/pathlib.html
Хотя на этот вопрос давно дан ответ. Я хочу порекомендовать использовать модуль pathlib
, поскольку это надежный способ работы в ОС Windows и Unix.
Итак, чтобы получить все пути в определенном каталоге, включая подкаталоги:
from pathlib import Path
paths = list(Path('myhomefolder', 'folder').glob('**/*.txt'))
# all sorts of operations
file = paths[0]
file.name
file.stem
file.parent
file.suffix
и т.п.
Спасибо за советы ребята. У меня возникла проблема с возвращением программных ссылок (бесконечная рекурсия) в виде каталогов. Софтлинки? Мы не хотим никаких вонючих софт-ссылок! Так...
Это отображало только каталоги, а не мягкие ссылки:
>>> import os
>>> inf = os.walk('.')
>>> [x[0] for x in inf]
['.', './iamadir']
[x[0] for x in inf]
называется в Python, чтобы я мог его найти?
- person shinzou; 23.12.2017
Скопируйте и вставьте в ipython
:
import os
d='.'
folders = list(filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d)))
Вывод из print(folders)
:
['folderA', 'folderB']
x
- это элемент из списка, созданного os.listdir(d)
, потому что listdir
вернет файлы и папки, которые он использует команду filter
с os.path.isdir
, чтобы отфильтровать любые файлы из списка.
- person James Burke; 28.05.2019
Вот несколько простых функций, основанных на примере @Blair Conrad:
import os
def get_subdirs(dir):
"Get a list of immediate subdirectories"
return next(os.walk(dir))[1]
def get_subfiles(dir):
"Get a list of immediate subfiles"
return next(os.walk(dir))[2]
Вот как я это делаю.
import os
for x in os.listdir(os.getcwd()):
if os.path.isdir(x):
print(x)
Основываясь на решении Эли Бендерски, используйте следующий пример:
import os
test_directory = <your_directory>
for child in os.listdir(test_directory):
test_path = os.path.join(test_directory, child)
if os.path.isdir(test_path):
print test_path
# Do stuff to the directory "test_path"
где <your_directory>
- это путь к каталогу, по которому вы хотите пройти.
С полным путем и учетом пути .
, ..
, \\
, ..\\..\\subfolder
и т. Д .:
import os, pprint
pprint.pprint([os.path.join(os.path.abspath(path), x[0]) \
for x in os.walk(os.path.abspath(path))])
Кажется, этого ответа еще не существовало.
directories = [ x for x in os.listdir('.') if os.path.isdir(x) ]
Недавно у меня был аналогичный вопрос, и я обнаружил, что лучший ответ для python 3.6 (как добавлено пользователем havlock) - использовать os.scandir
. Поскольку кажется, что с его помощью нет решения, я добавлю свое. Во-первых, нерекурсивное решение, в котором перечислены только подкаталоги непосредственно в корневом каталоге.
def get_dirlist(rootdir):
dirlist = []
with os.scandir(rootdir) as rit:
for entry in rit:
if not entry.name.startswith('.') and entry.is_dir():
dirlist.append(entry.path)
dirlist.sort() # Optional, in case you want sorted directory names
return dirlist
Рекурсивная версия будет выглядеть так:
def get_dirlist(rootdir):
dirlist = []
with os.scandir(rootdir) as rit:
for entry in rit:
if not entry.name.startswith('.') and entry.is_dir():
dirlist.append(entry.path)
dirlist += get_dirlist(entry.path)
dirlist.sort() # Optional, in case you want sorted directory names
return dirlist
имейте в виду, что entry.path
имеет абсолютный путь к подкаталогу. Если вам нужно только имя папки, вы можете использовать вместо него entry.name
. См. os.DirEntry. для получения дополнительных сведений об объекте entry
.
Самый простой способ:
from pathlib import Path
from glob import glob
current_dir = Path.cwd()
all_sub_dir_paths = glob(str(current_dir) + '/*/') # returns list of sub directory paths
all_sub_dir_names = [Path(sub_dir).name for sub_dir in all_sub_dir_paths]
используйте функцию фильтра os.path.isdir
поверх os.listdir()
примерно так filter(os.path.isdir,[os.path.join(os.path.abspath('PATH'),p) for p in os.listdir('PATH/')])
Это перечислит все подкаталоги прямо вниз по дереву файлов.
import pathlib
def list_dir(dir):
path = pathlib.Path(dir)
dir = []
try:
for item in path.iterdir():
if item.is_dir():
dir.append(item)
dir = dir + list_dir(item)
return dir
except FileNotFoundError:
print('Invalid directory')
pathlib
является новым в версии 3.4
Функция для возврата списка всех подкаталогов в пределах заданного пути к файлу. Будет искать во всем дереве файлов.
import os
def get_sub_directory_paths(start_directory, sub_directories):
"""
This method iterates through all subdirectory paths of a given
directory to collect all directory paths.
:param start_directory: The starting directory path.
:param sub_directories: A List that all subdirectory paths will be
stored to.
:return: A List of all sub-directory paths.
"""
for item in os.listdir(start_directory):
full_path = os.path.join(start_directory, item)
if os.path.isdir(full_path):
sub_directories.append(full_path)
# Recursive call to search through all subdirectories.
get_sub_directory_paths(full_path, sub_directories)
return sub_directories
мы можем получить список всех папок с помощью os.walk ()
import os
path = os.getcwd()
pathObject = os.walk(path)
этот pathObject является объектом, и мы можем получить массив,
arr = [x for x in pathObject]
arr is of type [('current directory', [array of folder in current directory], [files in current directory]),('subdirectory', [array of folder in subdirectory], [files in subdirectory]) ....]
Мы можем получить список всех подкаталогов, перебирая arr и печатая средний массив
for i in arr:
for j in i[1]:
print(j)
Это напечатает весь подкаталог.
Чтобы получить все файлы:
for i in arr:
for j in i[2]:
print(i[0] + "/" + j)
Присоединившись к нескольким решениям отсюда, я в итоге использовал следующее:
import os
import glob
def list_dirs(path):
return [os.path.basename(x) for x in filter(
os.path.isdir, glob.glob(os.path.join(path, '*')))]
Этот ниже класс сможет получить список файлов, папок и всех подпапок внутри данного каталога.
import os
import json
class GetDirectoryList():
def __init__(self, path):
self.main_path = path
self.absolute_path = []
self.relative_path = []
def get_files_and_folders(self, resp, path):
all = os.listdir(path)
resp["files"] = []
for file_folder in all:
if file_folder != "." and file_folder != "..":
if os.path.isdir(path + "/" + file_folder):
resp[file_folder] = {}
self.get_files_and_folders(resp=resp[file_folder], path= path + "/" + file_folder)
else:
resp["files"].append(file_folder)
self.absolute_path.append(path.replace(self.main_path + "/", "") + "/" + file_folder)
self.relative_path.append(path + "/" + file_folder)
return resp, self.relative_path, self.absolute_path
@property
def get_all_files_folder(self):
self.resp = {self.main_path: {}}
all = self.get_files_and_folders(self.resp[self.main_path], self.main_path)
return all
if __name__ == '__main__':
mylib = GetDirectoryList(path="sample_folder")
file_list = mylib.get_all_files_folder
print (json.dumps(file_list))
В то время как примерный каталог выглядит как
sample_folder/
lib_a/
lib_c/
lib_e/
__init__.py
a.txt
__init__.py
b.txt
c.txt
lib_d/
__init__.py
__init__.py
d.txt
lib_b/
__init__.py
e.txt
__init__.py
Результат получен
[
{
"files": [
"__init__.py"
],
"lib_b": {
"files": [
"__init__.py",
"e.txt"
]
},
"lib_a": {
"files": [
"__init__.py",
"d.txt"
],
"lib_c": {
"files": [
"__init__.py",
"c.txt",
"b.txt"
],
"lib_e": {
"files": [
"__init__.py",
"a.txt"
]
}
},
"lib_d": {
"files": [
"__init__.py"
]
}
}
},
[
"sample_folder/lib_b/__init__.py",
"sample_folder/lib_b/e.txt",
"sample_folder/__init__.py",
"sample_folder/lib_a/lib_c/lib_e/__init__.py",
"sample_folder/lib_a/lib_c/lib_e/a.txt",
"sample_folder/lib_a/lib_c/__init__.py",
"sample_folder/lib_a/lib_c/c.txt",
"sample_folder/lib_a/lib_c/b.txt",
"sample_folder/lib_a/lib_d/__init__.py",
"sample_folder/lib_a/__init__.py",
"sample_folder/lib_a/d.txt"
],
[
"lib_b/__init__.py",
"lib_b/e.txt",
"sample_folder/__init__.py",
"lib_a/lib_c/lib_e/__init__.py",
"lib_a/lib_c/lib_e/a.txt",
"lib_a/lib_c/__init__.py",
"lib_a/lib_c/c.txt",
"lib_a/lib_c/b.txt",
"lib_a/lib_d/__init__.py",
"lib_a/__init__.py",
"lib_a/d.txt"
]
]
Эта функция с заданным родителем directory
рекурсивно перебирает все свои directories
и prints
все filenames
, которые она находит внутри. Слишком полезно.
import os
def printDirectoryFiles(directory):
for filename in os.listdir(directory):
full_path=os.path.join(directory, filename)
if not os.path.isdir(full_path):
print( full_path + "\n")
def checkFolders(directory):
dir_list = next(os.walk(directory))[1]
#print(dir_list)
for dir in dir_list:
print(dir)
checkFolders(directory +"/"+ dir)
printDirectoryFiles(directory)
main_dir="C:/Users/S0082448/Desktop/carpeta1"
checkFolders(main_dir)
input("Press enter to exit ;")
Есть много хороших ответов, но если вы пришли сюда в поисках простого способа получить список всех файлов или папок сразу. Вы можете воспользоваться преимуществами операционной системы, предлагаемой find в Linux и Mac, которая намного быстрее, чем os.walk.
import os
all_files_list = os.popen("find path/to/my_base_folder -type f").read().splitlines()
all_sub_directories_list = os.popen("find path/to/my_base_folder -type d").read().splitlines()
OR
import os
def get_files(path):
all_files_list = os.popen(f"find {path} -type f").read().splitlines()
return all_files_list
def get_sub_folders(path):
all_sub_directories_list = os.popen(f"find {path} -type d").read().splitlines()
return all_sub_directories_list
Это должно сработать, поскольку оно также создает дерево каталогов;
import os
import pathlib
def tree(directory):
print(f'+ {directory}')
print("There are " + str(len(os.listdir(os.getcwd()))) + \
" folders in this directory;")
for path in sorted(directory.glob('*')):
depth = len(path.relative_to(directory).parts)
spacer = ' ' * depth
print(f'{spacer}+ {path.name}')
В нем должны быть перечислены все каталоги в папке, использующей библиотеку pathlib
. path.relative_to(directory).parts
получает элементы относительно текущего рабочего каталога.
os.path.join
на o
, чтобы получить полный путь, иначе isdir(0)
всегда будет возвращать false
- person James McMahon; 23.08.2012
os.path.join
дважды, вы можете сначала присоединиться, а затем отфильтровать список, используя os.path.isdir
: filter(os.path.isdir, [os.path.join(d, o) for o in os.listdir(d)])
- person quant_dev; 14.06.2019
[f for f in data_path.iterdir() if f.is_dir()]
или glob намного проще и легче для чтения: glob.glob("/path/to/directory/*/")
.
- person Charlie Parker; 20.07.2020
[f for f in data_path.iterdir() if f.is_dir()]
кредит: stackoverflow.com/a/44228436/1601580. это дает вам имена папок в виде строк. Как-то также исключает.
и..
слава богу. Решение Glob тоже стоит того:glob.glob("/path/to/directory/*/")
. - person Charlie Parker   schedule 20.07.2020